Commit Graph
8 Commits
Author SHA1 Message Date
m038andClaude Opus 4.8 b8daea217d feat(post-form): U6 — owner-scoped delete API route + card wiring
New custom-in-repo plugin entry-actions (un-ignored in .gitignore, NOT in
plugins.txt) registers DELETE /api/v1/entry/{slug} via onApiRegisterRoutes
(KTD5). The handler requires the authenticated site OWNER (not any login/admin),
rejects unsafe slugs (400), resolves the target through the page tree, asserts it
is a direct child of the active trip's dailies container, deletes the folder and
clears the cache — sharing EntryScopeGuard with the save path so R6 can't diverge.
A lazy per-namespace autoloader loads the controller on cached-route requests
(the router dispatches from route.cache without re-firing onApiRegisterRoutes).
EntryScopeGuard gains isOwnerUser() (API user comes from the request, not
$grav['user']) and enablePages() before find() (pages are lazily disabled in the
API context).

feed-actions.js (new, built via make build-assets; loaded on the trip/home feed
only when owner_can_edit) wires the inline Delete → Cancel/Confirm swap: on
Confirm it locks both buttons (D2, no double-DELETE), fetches the route
(credentials:include), removes the card, moves focus to the next card, and
announces via a page-level aria-live region (D4); on failure it restores the
control with an inline message (D7). Adds .sr-only + .entry-action[hidden] CSS.

Verified on the 2.0.4 container — API matrix 8/8 (anon 401, non-owner 403, bad
slug 400, out-of-scope 404, owner 204 + folder removed; V3/V5) and the delete UI
in a headless browser (confirm swap, card removal, disk deletion, live announce).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H1FrCYNq6RXdGYbn5PFrhM
2026-07-05 00:19:15 +02:00
m038andClaude Opus 4.8 4e91492f65 feat(post-form): U2 — server-side active-trip + owner scope guard on edit save
Enforce R6 on the save path (KTD6): in cache-on-save's onFormValidationProcessed,
when a hidden edit_path is present, require the site owner (not merely any login —
the super-admin tester also authenticates) AND that the target resolves through
the page tree to a direct child of the active trip's dailies container. Fail
closed with a ValidationException so add_page never runs. Create (empty edit_path)
is left untouched.

New shared EntryScopeGuard (classes/EntryScopeGuard.php) is the single source of
truth for both R6 enforcement points — this save guard and U6's delete route call
the same isOwner()/resolveActiveDailyChild()/segment helpers, so they cannot
diverge (KTD5). Resolution is via $pages->find() + a parent-route assertion, never
raw path concatenation, closing the traversal hole (basename(dirname()) yields the
same target add-page-by-form writes to).

Verified on the 2.0.4 container: non-owner edit, out-of-scope edit_path, unsafe
'..' segment, and non-dailies-child targets are all rejected; owner in-place edit
succeeds (V3).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H1FrCYNq6RXdGYbn5PFrhM
2026-07-04 23:40:04 +02:00
m038andClaude Opus 4.8 aa5d34717e feat(post-form): U1 — shared create/edit form + published field + owner_username
One /post form now drives both create and edit (KTD1, Alt B): cache-on-save
toggles add-page-by-form's overwrite_mode per submit — 'edit' when the new hidden
edit_path field is filled (write back in place, stable URL), 'false' when empty
(fresh dated folder via slug_field). add-page-by-form stays stock (no fork);
the toggle lives in cache-on-save, which reads edit_path and mutates the /post
page header's pageconfig before add-page-by-form's onFormProcessed runs.

- post-form.md: overwrite_mode:false (create-safe fallback), hidden edit_path,
  authoritative published toggle (default on), removed the static
  pagefrontmatter.published so the field wins on every submit (KTD3).
- cache-on-save.php: editPathFromForm + setOverwriteMode helpers.
- site.yaml: owner_username (single source of truth for the KTD8 owner gate).

Verified against the 2.0.4 container: create writes a fresh dated folder with
published:true/false as a real boolean (V1, V2); edit writes in place with the
slug/URL unchanged; save-as-draft-on-create works.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H1FrCYNq6RXdGYbn5PFrhM
2026-07-04 23:31:25 +02:00
m038andClaude Opus 4.8 d17d1256ba feat(post-form): dark-theme the photo widget + drag-to-reorder that sticks
Styling: repaint FilePond's default light drop zone/thumbnails/actions with
the Field Notes dark tokens so the picker matches the site palette.

Reordering: enable FilePond drag-reorder (allowReorder, itemInsertLocation
'after'). FilePond does NOT re-sequence its submitted data[photos][] inputs on
reorder, so post-form.js sends the visual order as a top-level `photo_order`
POST key on submit. cache-on-save reads it from $_POST (after add-page-by-form
copies the files, priority -100) and renames them photo-1..N in that order —
which the entry honours since it lists media by filename and treats the first
as hero. The order key is top-level (not data[...]), so it never lands in the
entry frontmatter. Best-effort + self-idempotent: locates the new entry folder
by the uploaded filenames and no-ops if they're already renamed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 20:25:56 +02:00
m038 817c20c24a feat(post-form): inject active-trip parent server-side (U1)
Derive the entry write target from site.active_trip at submit time in
cache-on-save's onFormValidationProcessed handler, and fail closed
(ValidationException) when no active trip is set. Removes the hardcoded
pageconfig.parent that had to be hand-synced with active_trip.

Refs R1, R2, AE2, KTD1.
2026-07-04 15:29:07 +02:00
m038andClaude Sonnet 4.6 c05b9e3400 feat: add Grav 2.0 compat flag for cache-on-save plugin and switch GPM to testing channel
- Add blueprints.yaml for cache-on-save plugin with Grav 2.0 support
- Update system.yaml GPM setting from stable to testing channel
- Update .gitignore to allow cache-on-save plugin tracking

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 23:19:27 +02:00
m038andClaude Sonnet 4.6 8ddc1af5c0 Fix cache-on-save plugin: use deleteAll() not clear()
Grav\Common\Cache has no clear() method in this version; the correct
method is deleteAll().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:30:01 +02:00
m038andClaude Sonnet 4.6 fdb423d2c7 Fix BUG-001 and BUG-002; add post-submission QA test plan and QA entry
BUG-001: cache-on-save plugin clears page cache on onFormProcessed so
new entries appear in the tracker feed immediately after submission.

BUG-002: disabled Twig template cache (twig.cache: false) so theme
file changes take effect without a manual cache flush.

Also adds bugs-and-fixes.md, corrects TC-P test URLs (.entry suffix),
fixes TC-P.1 expectation (inline login form, not a redirect), and
creates the QA test entry for automated scenario verification.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:21:26 +02:00