224 lines
11 KiB
Markdown
224 lines
11 KiB
Markdown
---
|
|
phase: 15-journal-plugin
|
|
plan: 02
|
|
subsystem: plugins
|
|
tags: [journal, cabana, mlmarkdown, goldmark, bonfire, admin, import-export]
|
|
|
|
requires:
|
|
- phase: 15-01
|
|
provides: "sm-journal-plugin ID golem15.journal Requires golem15.translate, squashed golem15_journal_* schema, host gitlink + TestBootUserTranslateJournal"
|
|
provides:
|
|
- "Posts/Categories/Tags YAML admin with mltext/mlmarkdown and FormatHTML on save"
|
|
- "HasPermissions/HasNavigation/HasSettings; journal-icon.svg embedded in AdminFS"
|
|
- "journal:export-posts and journal:import-posts plus Posts toolbar access_import_export"
|
|
affects: [15-03, 15-04, 16]
|
|
|
|
actuals:
|
|
tokens: 22500
|
|
tasks: 3
|
|
commits: 6
|
|
plan_head_before: 8d7979f87e33fec150ff1c2eb9e518e8bd6f837b
|
|
plugin_repo_head_after: 4ff98f7de85a6404987373ad5630b17fc5542ade
|
|
host_repo_head_after: d09583ef2825e5fa73b7d5e4cca953834a018c6e
|
|
|
|
tech-stack:
|
|
added: ["github.com/yuin/goldmark v1.8.6 (plugin FormatHTML)"]
|
|
patterns:
|
|
- "Admin YAML embed file-by-file; NavigationItem has no IconSvg so journal-icon.svg is go:embed in AdminFS"
|
|
- "preset is valid only on type: text; post/category mltext slugs omit preset"
|
|
- "PHP journal:export-posts/import-posts are JSON-per-slug files, not Winter CSV; toolbar HasAdminActions names are not create/delete"
|
|
- "Host gitlink is a nested clone; bump via file:// fetch with protocol.file.allow=always"
|
|
|
|
key-files:
|
|
created:
|
|
- ../sm-journal-plugin/admin.go
|
|
- ../sm-journal-plugin/admin_permissions.go
|
|
- ../sm-journal-plugin/admin_navigation.go
|
|
- ../sm-journal-plugin/assets/images/journal-icon.svg
|
|
- ../sm-journal-plugin/classes/format_html.go
|
|
- ../sm-journal-plugin/controllers/posts.go
|
|
- ../sm-journal-plugin/controllers/categories.go
|
|
- ../sm-journal-plugin/controllers/tags.go
|
|
- ../sm-journal-plugin/console/export_posts.go
|
|
- ../sm-journal-plugin/console/import_posts.go
|
|
- ../sm-journal-plugin/console/columns.go
|
|
- ../sm-journal-plugin/posts_admin_smoke_test.go
|
|
modified:
|
|
- ../sm-journal-plugin/plugin.go
|
|
- ../sm-journal-plugin/models/post.go
|
|
- ../sm-journal-plugin/models/post/fields.yaml
|
|
- ../sm-journal-plugin/README.md
|
|
- ../sm-grzybyfunkcjonalne-app/boot_test.go
|
|
- ../sm-grzybyfunkcjonalne-app/plugins/golem15/journal
|
|
|
|
key-decisions:
|
|
- "D-11 is a no-op: post content is mlmarkdown; cabana.RenderMarkdown is not edited; FormatHTML lives in the plugin with goldmark Footnote+Table+WithAttribute plus rejectUnsafe"
|
|
- "user_id is WritableForeignKey; FormBeforeCreate stamps it when empty; without access_other_posts List/FormExtendQuery restrict to principal user_id (fail-closed)"
|
|
- "publish without access_publish returns ForbiddenError; toolbar import uses the same guard"
|
|
- "CLI is JSON files per slug (--path, --dry-run, --force) matching PHP ExportPosts/ImportPosts; PostExport/PostImport column names are the shared field list, not a CSV framework"
|
|
- "Toolbar extra buttons exportPosts/importPosts require golem15.journal.access_import_export; names are not create or delete"
|
|
|
|
patterns-established:
|
|
- "Compiled journal admin: HasAdminControllers + file-by-file YAML embed + SVG in AdminFS"
|
|
- "FilterCategories expands NestedTree children via nest_left/nest_right; switch published uses column: published"
|
|
- "HasCommands registers PHP command names; HasAdminActions toolbar reuses console.ExportToDir/ImportFromDir"
|
|
|
|
requirements-completed: [D-04, D-06, D-08, D-10, D-11, D-13]
|
|
|
|
coverage:
|
|
- id: D1
|
|
description: "Posts admin YAML with mltext/mlmarkdown, FormatHTML on save, nav SVG embed, access_posts and author/publish guards"
|
|
requirement: D-04
|
|
verification:
|
|
- kind: integration
|
|
ref: "../sm-journal-plugin#TestPostsFormCompiles"
|
|
status: pass
|
|
- kind: integration
|
|
ref: "../sm-journal-plugin#TestPostsAdminCreateSmoke"
|
|
status: pass
|
|
human_judgment: false
|
|
- id: D2
|
|
description: "Categories, Tags, and settings singleton registered; host cabana.Activate sees golem15.journal.posts|categories|tags and settings code journal"
|
|
requirement: D-04
|
|
verification:
|
|
- kind: integration
|
|
ref: "../sm-grzybyfunkcjonalne-app#TestBootUserTranslateJournal"
|
|
status: pass
|
|
human_judgment: false
|
|
- id: D3
|
|
description: "journal:export-posts and journal:import-posts registered; Posts toolbar exportPosts/importPosts require golem15.journal.access_import_export"
|
|
requirement: D-13
|
|
verification:
|
|
- kind: unit
|
|
ref: "../sm-journal-plugin#TestJournalCommands"
|
|
status: pass
|
|
human_judgment: false
|
|
- id: D4
|
|
description: "Post content YAML type is mlmarkdown; title/slug/excerpt are mltext; cabana markdown types were not re-added"
|
|
requirement: D-10
|
|
verification:
|
|
- kind: other
|
|
ref: "../sm-journal-plugin/models/post/fields.yaml"
|
|
status: pass
|
|
human_judgment: false
|
|
- id: D5
|
|
description: "No Winter.Pages menu types and no dashboard widget in plugin.go or admin_navigation.go; README stays application-neutral"
|
|
requirement: D-13
|
|
verification:
|
|
- kind: other
|
|
ref: "../sm-journal-plugin/plugin.go"
|
|
status: pass
|
|
human_judgment: false
|
|
|
|
duration: 75min
|
|
completed: 2026-10-06
|
|
status: complete
|
|
---
|
|
|
|
# Phase 15: Journal plugin plan 02 Summary
|
|
|
|
**YAML-driven Posts/Categories/Tags admin with plugin FormatHTML, plus JSON journal:export-posts/import-posts and a permissioned Posts toolbar**
|
|
|
|
## Performance
|
|
|
|
- **Duration:** 75 min
|
|
- **Started:** 2026-10-06T15:30:00Z
|
|
- **Completed:** 2026-10-06T16:48:34Z
|
|
- **Tasks:** 3
|
|
- **Files modified:** 39
|
|
|
|
## Accomplishments
|
|
- Posts, Categories, and Tags admin controllers boot from adapted YAML (`mltext`/`mlmarkdown`); nav embeds `assets/images/journal-icon.svg`
|
|
- `classes.FormatHTML` regenerates `content_html` on admin save (goldmark footnote/table/attribute + rejectUnsafe) without editing `cabana.RenderMarkdown`
|
|
- Without `access_other_posts`, list/form queries restrict to the backend principal; publish without `access_publish` returns `ForbiddenError`
|
|
- `journal:export-posts` / `journal:import-posts` match PHP JSON-per-slug CLI flags; Posts toolbar `exportPosts`/`importPosts` require `golem15.journal.access_import_export`
|
|
- Proof host `TestBootUserTranslateJournal` still activates user+translate+journal after the gitlink bump to `4ff98f7`
|
|
|
|
## Task Commits
|
|
|
|
Each task was committed atomically in the owning repo:
|
|
|
|
1. **Task 1: Posts admin + mlmarkdown + FormatHTML** - `dea0934950a290b98feb3dbe66c5b066a5c8b0a9` (feat) sm-journal-plugin
|
|
2. **Task 2: Categories, Tags, Settings + query guards**
|
|
- `afd0a2cafcc62fcfb13359530147ae798349cfa1` (feat) sm-journal-plugin
|
|
- `ab0656964103aef4bc91553818447981e9c91b1d` (fix) gofmt settings.go
|
|
- `469182d4103343fd1cd6f71b88668e0c658c0dfc` (feat) host gitlink + boot_test controller/settings assertions
|
|
3. **Task 3: export/import commands + Posts toolbar**
|
|
- `4ff98f7de85a6404987373ad5630b17fc5542ade` (feat) sm-journal-plugin
|
|
- `d09583ef2825e5fa73b7d5e4cca953834a018c6e` (chore) host gitlink `4ff98f7`
|
|
|
|
**Plan metadata:** (this commit)
|
|
|
|
## Files Created/Modified
|
|
- `../sm-journal-plugin/controllers/posts.go` - Posts controller, query guards, FormatHTML hook, HasAdminActions
|
|
- `../sm-journal-plugin/classes/format_html.go` - plugin markdown HTML (not cabana.RenderMarkdown)
|
|
- `../sm-journal-plugin/models/post/fields.yaml` - mltext title/slug/excerpt, mlmarkdown content
|
|
- `../sm-journal-plugin/console/export_posts.go` - `journal:export-posts`
|
|
- `../sm-journal-plugin/console/import_posts.go` - `journal:import-posts`
|
|
- `../sm-journal-plugin/README.md` - CLI command names with acme/blog examples
|
|
- `../sm-grzybyfunkcjonalne-app/plugins/golem15/journal` - gitlink `4ff98f7`
|
|
|
|
## Decisions Made
|
|
- D-11 no-op: keep existing cabana `mlmarkdown`; FormatHTML is plugin-local goldmark with footnote/table/attribute plus the same rejectUnsafe gate
|
|
- `preset` omitted on mltext slugs (cabana allows preset only on `type: text`); tag slug stays `type: text` with preset
|
|
- PHP CLI is JSON files, not Winter CSV; shared column sets are `ExportColumns`/`ImportColumns`; `--force` is included because PHP ImportPosts has it
|
|
- Toolbar import refuses published writes without `access_publish` (CLI has no principal)
|
|
- Navigation SVG is go:embed; `NavigationItem` has no IconSvg field
|
|
|
|
## Deviations from Plan
|
|
|
|
### Auto-fixed Issues
|
|
|
|
**1. [Rule 3 - Blocking] preset on mltext fails schema compile**
|
|
- **Found during:** Task 1 (YAML compile)
|
|
- **Issue:** cabana accepts `preset` only on `type: text`; PHP post/category slugs are mltext
|
|
- **Fix:** Drop preset on post and category slugs; keep it on tag slug (`type: text`)
|
|
- **Files modified:** `../sm-journal-plugin/models/post/fields.yaml`, `models/category/fields.yaml`
|
|
- **Verification:** `TestPostsFormCompiles` PASS
|
|
- **Committed in:** `dea0934` (Task 1)
|
|
|
|
**2. [Rule 3 - Blocking] nav cannot name unknown controllers**
|
|
- **Found during:** Task 1 (`cabana.Activate`)
|
|
- **Issue:** Task 1 nav listing categories/tags fails boot until those controllers exist
|
|
- **Fix:** Defer categories/tags side-menu entries to Task 2
|
|
- **Files modified:** `../sm-journal-plugin/admin_navigation.go`
|
|
- **Verification:** Task 1 smoke PASS; Task 2 `TestBootUserTranslateJournal` PASS
|
|
- **Committed in:** `dea0934` / `afd0a2c`
|
|
|
|
**3. [Rule 3 - Blocking] goldmark must be a direct plugin require**
|
|
- **Found during:** Task 1 (`go get` / FormatHTML import)
|
|
- **Issue:** FormatHTML imports goldmark; tidy via HTTPS could not resolve sm-translate-plugin without go.work
|
|
- **Fix:** Direct-require goldmark v1.8.6 (and gocloud.dev already used by admin smokes); run vet/test with `GOWORK=plugin/go.work`
|
|
- **Files modified:** `../sm-journal-plugin/go.mod`
|
|
- **Verification:** `go vet ./...` PASS
|
|
- **Committed in:** `dea0934` (Task 1)
|
|
|
|
**4. [gofmt] settings.go left unstaged after Task 2 commit**
|
|
- **Found during:** Task 2 (post-commit `git status`)
|
|
- **Issue:** gofmt rewrote `models/settings.go` after the feat commit; amend is disallowed
|
|
- **Fix:** Separate fix commit
|
|
- **Files modified:** `../sm-journal-plugin/models/settings.go`
|
|
- **Verification:** `gofmt` clean
|
|
- **Committed in:** `ab06569` (Task 2 fix)
|
|
|
|
---
|
|
|
|
**Total deviations:** 4 auto-fixed (3 blocking compile/boot, 1 gofmt follow-up)
|
|
**Impact on plan:** Required for cabana schema boot and FormatHTML. No scope creep. CLI is JSON (PHP) rather than inventing CSV.
|
|
|
|
## Issues Encountered
|
|
- Plan verify `go test ./... -run '^(TestJournalCommands)$'` (and Task 1 `TestPosts*`) prints `[no tests to run]` / `[no test files]` for `models`, `updates`, `classes`, `console`, `controllers`. Named tests still `--- PASS`. Same leaf-package shape as 15-01; stubs were not added.
|
|
- Host `go test` must run with `GOWORK` unset so it does not inherit the plugin workspace
|
|
- Nested host gitlink is a separate clone from sibling `sm-journal-plugin`; bump with `git -c protocol.file.allow=always fetch file://…`
|
|
- Journal remote still has no refs; gitlink records local SHA `4ff98f7`. Do not push unless asked
|
|
|
|
## User Setup Required
|
|
None - no external service configuration required.
|
|
|
|
## Next Phase Readiness
|
|
Ready for 15-03 (`/_journal/api/v1`, buckets, backend Bearer writes, media, Typesense gate off). Admin screens and import/export CLI are in. Pages menu types and dashboard widgets remain absent by design.
|
|
|
|
---
|
|
*Phase: 15-journal-plugin*
|
|
*Completed: 2026-10-06*
|