16 KiB
phase, plan, subsystem, tags, requires, provides, affects, actuals, plan_head_before, plan_head_after, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, coverage, duration, completed, status
| phase | plan | subsystem | tags | requires | provides | affects | actuals | plan_head_before | plan_head_after | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | coverage | duration | completed | status | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 12.2-admin-form-fields-date-file-upload-relation-editing-with-def | 05 | testing |
|
|
|
|
|
162a8ec5a1 |
912a466 |
|
|
|
|
|
|
54min | 2026-10-02 | awaiting-checkpoint |
Phase 12.2 Plan 05: Unit, integration and security tests, phase gate and release checklist Summary
This plan adds an acme.deferred fixture plugin that proves through the real router that no child, pivot row or file of another parent or admin can be reached. That proof fails when the parent scoping is removed. Go and SPA tests now cover every Phase 12.2 behaviour, and a nine-stage gate passes end to end. The user then tags v0.1.1.
Performance
- Duration: about 54 min
- Started: 2026-10-02T18:01:19Z
- Paused at the checkpoint: 2026-10-02T18:55:00Z
- Tasks: 3 of 4 done. Task 4 is the user's v0.1.1 tag, a blocking-human checkpoint.
- Files: 51 created or modified in summercms.go. fonoteka.go was not changed.
Accomplishments
-
Fixture plugin
acme.deferred(test-only,os.DirFS(testdata/deferred)). It has two controllers:gadgets: datepicker date, datetime and time fields; a public attachManyphotosand a protected attachOnemanual; a belongsToManymemberswith manage and pivot forms (RelationBeforeLink stampsrole); and a deferrable hasManypartson a soft-deletable model, whose manage form has an image field, an attachOne field and a datepicker.locked: a reduced toolbar and a required fileupload.
FormExtendQuery hides rows whose
hiddencolumn is true. Every Form and Relation hook records its calls and can be made to fail. Admins A and B, a memblob bucket anddfOverlaygive per-test YAML edits. -
D-15 and D-10 security suites. A child, pivot row or file of another parent is 404
not_foundon all 12 child routes and changes nothing (row, file, binding and blob snapshots are compared). The same holds through a FormExtendQuery-hidden parent and through another admin's session key. An owning-parent control runs the same routes with 2xx, which shows each 404 comes from the scope. The protected routes serve only the four image types inline and always send the D-10 headers. -
Go coverage of every behaviour.
- Date and TimeOfDay through real DATE and TIME columns. Fill, without changing earlier conversions.
requiredon zero dates. - The deferred_bindings shape, history and rollback. Store isolation and the envelope.
- PurgeDeferred: cut-off, after-commit blobs, rollback, SKIP LOCKED, the nil bucket,
--days, and the command end to end. - attach.Store limits and key shape. IsAllowedImage polyglots and the pixel ceiling.
- The framework schedule and forged jobs. The six hook interfaces.
- In cabana: fileupload and datepicker compile and routes; commit order, rollback, applied-only and concurrent saves; relation contracts, the zero-Kind equivalence, forms, CRUD, deferral and the schema.
- Date and TimeOfDay through real DATE and TIME columns. Fill, without changing earlier conversions.
-
SPA tests.
- sessionKey and dateFormat.
- DatepickerField: backstops 1 and 2.
- FileuploadField: backstops 3 and 4, plus states, retry, removal, caption and load failure.
- RelationChildModal and RelationPivotModal.
- RelationManager: row-action order, the pivot button, plural delete and create-screen deferral.
- Date and time cells.
-
Gate
scripts/check-phase12.2.sh. Its detector refuses a failure, a skip, zero tests, "no tests to run", a build failure or a missing named test, and--self-testproves it on planted inputs. A planted missing security test name was refused with exit 1.
Gate stage summary
FORCE_COLOR= bash scripts/check-phase12.2.sh --all on 2026-10-02 (about 3 min 16 s, Docker up):
PASS self-test
PASS go
PASS security
PASS spa (Test Files 60 passed, Tests 768 passed)
PASS openapi
PASS dist
PASS docs
PASS hygiene
PASS app (fonoteka.go build, vet, Admin tests, parity schema and migrate; tree clean)
phase12.2 all stages passed
Failing-when-broken check (Task 1)
The parent predicate in loadChild (modules/cabana/relation_child.go) was dropped by adding a matching case true: ahead of the scoped cases. go test ./modules/cabana -run '^TestRelationChildScope' -count=1 then failed:
relation_child_scope_test.go:97: GET records/{child} through G1: status=200 want 404 body={"data":{"due_on":null,"id":2,"label":"p2"},"meta":{"labels":{}}}
relation_child_scope_test.go:222: B show of A's pending part: status=200 want 404 body={"data":{"due_on":null,"id":1,"label":"pending-..."},"meta":{"labels":{}}}
The file was restored with git checkout -- modules/cabana/relation_child.go, and git diff --quiet confirmed it.
Task Commits
- Task 1: D-15 and D-10 suites with the fixture plugin -
9d2b1c1(test) - Task 2: every Go behaviour of the phase -
c8d41a6(test) - Task 3: SPA tests and the gate -
5b06b20(fix, see Deviations),d5494fa(test); planning docs912a466(docs) - Task 4: v0.1.1 tag: checkpoint, awaiting the user. Nothing was tagged or pushed.
The measured count of 6 commits since plan_head_before includes 9c87a59 docs(13): create phase plan. Another session committed it on master during this run, and it is not part of this plan.
Decisions Made
See key-decisions in the frontmatter.
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] A partly filled time-mode datepicker was never marked invalid
- Found during: Task 3 (DatepickerField tests)
- Issue:
refreshPartialread only[data-reka-date-field-segment]. Reka's TimeField marks its segmentsdata-reka-time-field-segment, so in time mode a half-typed value never gotaria-invalid. - Fix: It now reads both segment attributes. The test "marks a partly filled time invalid" failed before the fix and passes after it.
modules/boardwalk/distwas rebuilt. - Files modified: admin/src/components/form/fields/DatepickerField.vue, modules/boardwalk/dist
- Commit:
5b06b20
Fixture and scope adjustments
- The fixture tree is larger than listed. The plan named seven YAML files. The tree also has
controllers/locked/*(the "second fixture controller with a reduced toolbar"),models/gadget/locked_fields.yaml(a required fileupload) andmodels/member/fields.yaml(a manage form for belongsToMany create, update and delete). The locked list declarescreateso the required-fileupload save can run.photosgainedmaxFilesize: 0.5, so the 413 and the 422 size paths can be tested. - The fixture controller registers one widget action (
lookup). Without it, a widget field in a relation form fails on its action before the D-23 refusal. - Reorder through another gadget answers 422, not 404. Reorder takes the whole id set. A foreign id gives the same 422 set mismatch as an id that exists nowhere. The test asserts that the two answers are identical, so there is no existence oracle.
- TIME columns in test models use
type:time without time zone. GORM reads a baretype:timeas its own time type, and AutoMigrate would createtimestamptz. Production migrations are hand-written SQL, so they are unaffected. This is logged in deferred-items.md.
Total deviations: 1 auto-fixed bug and 4 fixture or scope adjustments.
Impact on plan: The fix is in production SPA code, in its own fix(12.2-05) commit with the test that proves it. Nothing else touches production code.
Issues Encountered
- Shared database. Other cabana tests leave bindings behind, so the fixture's state snapshot counts only the fixture's own morph types.
- Shared index.
git diff --cachedwas checked before every commit and each commit used explicit pathspecs. No foreign file was staged, and the other session's phase 13 files were not touched. - FORCE_COLOR. It was unset for every Go run.
Known Stubs
None.
Threat Flags
None. The plan adds tests, a gate script and docs. The only production change, the DatepickerField fix, adds no network, auth, file or schema surface.
User Setup Required
None for the tests. Task 4 needs the user (see below).
Checkpoint: v0.1.1 tag (Task 4, blocking-human)
- Read the gate stage summary above, or re-run
FORCE_COLOR= bash scripts/check-phase12.2.sh --all. - Read
12.2-SECURITY-REVIEW.md. Every high threat has a named passing test. - Run
/gsd-verify-work 12.2for the manual UI checks: calendar keyboard and visual fit, drag reorder and upload progress, and the child and pivot modal flow. - summercms.go has no tags yet, because v0.1.0 was deferred to the launch step in Phase 11.2. Decide whether to create v0.1.0 first on its intended commit.
- Tag and push it yourself:
git tag -a v0.1.1 -m "SummerCMS v0.1.1: datepicker, fileupload, relation child CRUD with deferred binding"on the phase head, thengit push origin master v0.1.1. - Tell the downstream project that its
TODO: requires SummerCMS changeitems for the date field, the file upload field and related-record editing can be resolved on v0.1.1.
Reply "tagged" or "defer tag".