docs(16.2): add phase verification report
This commit is contained in:
@@ -0,0 +1,248 @@
|
||||
---
|
||||
phase: 16.2-plugin-provided-field-types-and-the-blog-editor-formwidget
|
||||
verified: 2026-10-10T17:05:00Z
|
||||
status: human_needed
|
||||
score: 13/14 must-haves verified
|
||||
covered_files:
|
||||
- .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-01-PLAN.md
|
||||
- .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-01-SUMMARY.md
|
||||
- .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-02-PLAN.md
|
||||
- .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-02-SUMMARY.md
|
||||
- .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-03-PLAN.md
|
||||
- .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-03-SUMMARY.md
|
||||
- .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-04-PLAN.md
|
||||
- .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-04-SUMMARY.md
|
||||
- .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-05-PLAN.md
|
||||
- .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-05-SUMMARY.md
|
||||
- .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-06-PLAN.md
|
||||
- .planning/phases/16.2-plugin-provided-field-types-and-the-blog-editor-formwidget/16.2-06-SUMMARY.md
|
||||
- admin/src/app/fieldTypes.ts
|
||||
- admin/src/components/form/fields/MLPluginField.vue
|
||||
- admin/src/components/form/fields/PluginField.vue
|
||||
- admin/src/components/form/registry.ts
|
||||
- admin/src/views/FormView.vue
|
||||
- docs/backend/field-types.md
|
||||
- modules/cabana/crud.go
|
||||
- modules/cabana/field_type.go
|
||||
- modules/cabana/field_type_upload.go
|
||||
- modules/cabana/http.go
|
||||
- modules/cabana/relation_field.go
|
||||
- modules/cabana/tx_context.go
|
||||
- modules/pact/capabilities.go
|
||||
- scripts/check-phase16.2.sh
|
||||
covered_digest: "v2:sha256:9eb467f60a452579c8faedf8900a27909d5234623d4f6760fef9f5691bbf6d75"
|
||||
behavior_unverified: 1
|
||||
overrides_applied: 0
|
||||
behavior_unverified_items:
|
||||
- truth: "D-19 (amended): Journal category content uses blogeditor and is stripped and reported like post content; the 422 CheckHTML gate is retired"
|
||||
test: "On a Docker host run `bash scripts/check-phase16.2.sh postgres` (TestCategoriesAdminContent, TestCategoriesAdminBlogEditor); on UAT change one word of a category's content in the Blog Editor and save"
|
||||
expected: "Both Postgres tests pass; on UAT the save succeeds with no removal notice and the category page on the site shows the change"
|
||||
why_human: "The code is present and wired (fields.yaml type blogeditor, prepareCategoryWrite no longer refuses, the shared Decode is unit-tested), but the end-to-end category save only runs in the Docker-only harness and the UAT category step was never performed (WINDOWS entry 18)"
|
||||
human_verification:
|
||||
- test: "On a host with Docker, run `bash scripts/check-phase16.2.sh postgres` from summercms.go"
|
||||
expected: "TestFieldTypeSavePostgres, TestListRelationSearchPostgres, TestPostsFormCompiles, TestPostsAdminCreateSmoke, TestPostsAdminResaveKeepsHTML, TestPostsAdminSaveSanitizesHTML, TestCategoriesAdminContent, TestCategoriesAdminBlogEditor and TestJournalSVGEmbed all pass (closes WINDOWS 11, 12, 14, 15, 16, 20, 21)"
|
||||
why_human: "No Docker daemon on this host; the suites compile under go vet but have never run. They are the only end-to-end proof of the CR-01 and WR-04 Load changes, which landed after the UAT acceptance"
|
||||
- test: "D-19 on UAT: change one word of a category's content in the Blog Editor and save"
|
||||
expected: "The save succeeds with no removal notice; the category page shows the change"
|
||||
why_human: "WINDOWS entry 18; not among the four UAT steps the human ran"
|
||||
- test: "After the next deploy (v0.1.19 with the review fixes), save post 1 and post 64 untouched again and re-run the read-only md5 SELECT"
|
||||
expected: "md5(content), md5(content_html) and the post 64 en translation md5 equal the 16.2-05 snapshot; updated_at moved"
|
||||
why_human: "The UAT D-03 evidence was taken on the v0.1.18 binary. The review fixes changed Load (CR-01: blank content served as content_html; WR-04: '<'-prefixed values compared with content_html). By reading the code the served value for posts 1 and 64 is unchanged, but the deployed proof predates the change"
|
||||
- test: "Blog Editor preview pane in a real browser (quick 261010-iwu): toggle Preview in light and dark mode, narrow the window, put a <script> in a raw HTML block, add a YouTube embed and a relative /storage image"
|
||||
expected: "50/50 split that wraps below about 720px; the script does nothing in the pane; the embed shows a thumbnail card; the relative image resolves"
|
||||
why_human: "happy-dom cannot enforce iframe sandboxing, CSP or layout"
|
||||
- test: "Judgment-tier prohibition (plan 02): 'The element renders no iframe and no live raw HTML in the admin'. Confirm the preview pane folded in from quick 261010-iwu is an accepted exception"
|
||||
expected: "Human accepts that the sandboxed srcdoc iframe (empty sandbox, CSP meta, active content dropped, no src) does not violate the intent, or asks for a change"
|
||||
why_human: "The preview pane renders the post HTML inside an iframe in the admin, which reads against the literal prohibition text; the LLM judgment is that its intent (no YouTube iframe, no script-capable raw HTML in the admin DOM) still holds"
|
||||
---
|
||||
|
||||
# Phase 16.2: Plugin-provided field types and the Blog Editor formwidget Verification Report
|
||||
|
||||
**Phase Goal:** Plugins can register their own admin form field types (todo: cabana-richeditor-field-type), and the Journal plugin ships a first-class Blog Editor formwidget for post content (beyond the current markdown field or a plain rich editor) that edits imported HTML posts losslessly.
|
||||
**Verified:** 2026-10-10T17:05:00Z
|
||||
**Status:** human_needed
|
||||
**Re-verification:** No, initial verification
|
||||
|
||||
ROADMAP lists no success criteria and REQUIREMENTS.md has none for this phase, so the must-haves are the six plans' frontmatter truths, keyed to CONTEXT decisions D-01 to D-19. They are merged into 14 truths below.
|
||||
|
||||
## Goal Achievement
|
||||
|
||||
### Observable Truths
|
||||
|
||||
| # | Truth | Status | Evidence |
|
||||
|---|-------|--------|----------|
|
||||
| 1 | D-11: a plugin registers a value-bearing field type under a short alias; duplicate aliases across plugins and clashes with core types fail boot | ✓ VERIFIED | `pact.HasFormFieldTypes` (capabilities.go:491). `compileFieldTypes` (field_type.go:151) checks the alias pattern and core-type clash, and names both owners on a cross-plugin clash. It is called from `Activate` (http.go:99) and passed to `compileRegistryWithTypes`. `TestFieldTypeRegistry` and `TestFieldTypeCompile` pass in the gate |
|
||||
| 2 | D-12.1: plugin fields accept the general keys plus the type's Options; other keys and CheckOptions errors fail boot | ✓ VERIFIED | `pluginFieldKeys` and `fieldKeyAllowed`, plus `compilePluginField` running CheckOptions. `TestFieldTypeOptions` passes |
|
||||
| 3 | D-12.2 and D-10 (framework): Decode runs inside the save transaction per locale; FormFieldError becomes 422 with no write; other errors become an opaque 500; notices become meta.notices only when present | ✓ VERIFIED | crud.go:609-636: lift, then loadRecord, then `decodePluginFields`, then Fill, all inside `s.transaction`. crud.go:733 calls `localizeNotices`, and `RecordMeta.Notices` is `json:"notices,omitempty"`. WR-06 adds a 422 for a non-string translatable value. `TestFieldTypeDecode` and `TestFieldTypeNotices` pass |
|
||||
| 4 | D-12.3 and D-12.4: Show and the save response serve plugin fields through Load (per locale); list columns use ListValue | ✓ VERIFIED | `hydratePluginFields` is called in Show (crud.go:447) and in save (crud.go:728). `projectRowCtx` calls `ListValue` (http.go:1114). `TestFieldTypeLoad` and `TestFieldTypeListValue` pass |
|
||||
| 5 | D-03 (server half): on update, a value equal to the served value is neither decoded nor written | ✓ VERIFIED | `decodeOne` compares with `servedFieldValue` (Load over the loaded record) through `sameJSON` and skips. An untouched default-locale value is deleted from Projected. The behavioural test `TestFieldTypeUntouched` passes |
|
||||
| 6 | D-14 and D-06: translatable plugin types use cabana's ML lift, translation writer and hydrate; Form hooks read writes through `FieldWritesFromContext` | ✓ VERIFIED | Translations are decoded in place on the `mlValue` items that `applyMLTranslations` writes. `withFieldWrites` (crud.go:636) feeds `FieldWritesFromContext`. `TestFieldTypeWrites` passes |
|
||||
| 7 | D-13 and D-15: the SPA loads field-type assets globally after login; PluginField/MLPluginField bind `value` and `summer-change`; the schema carries plugin fields generically; OpenAPI, TS types, dist and docs are regenerated | ✓ VERIFIED | `loadFieldTypes` is called in main.ts:26 and LoginView.vue:33. `registry.ts` routes any field with `element` to PluginField or MLPluginField. PluginField only re-sets `value` when it differs (echo guard). admin.json and schema.d.ts carry `element`, `translatable` and `typeOptions`. Gate docs stage: check-admin-openapi, check-admin-dist and TestDocsTree pass. Vitest 1218/1218 |
|
||||
| 8 | D-18: cabana-owned upload route (guard, X-Requested-With, permissions, declared op, record scope, body cap) answers 201 {data:{url}}; Journal Upload accepts only sniffed jpg/jpeg/png/gif/webp up to 10240 KiB | ✓ VERIFIED | Route at http.go:360, wrapped in `requireAjax`. `fieldUpload` calls `protect` and `operationDeclared` (WR-01), reads the whole body before Upload (WR-02) and scopes the record through `loadRecord`. Journal `uploadBlogImage` sniffs the bytes. `StoreMedia` enforces the extension allowlist, so a PNG named `.svg` is refused there, and caps the size. `TestFieldUpload`, `TestBlogEditorUpload` and `TestStoreMedia` pass. UAT edit-ok shows an image under journal/posts |
|
||||
| 9 | D-01, D-04, D-16: Blog Editor is a TipTap WYSIWYG custom element `golem15-journal-blogeditor` with a source tab, a toolbar (headings, marks, lists, links, blockquote, tables, images, embeds, raw HTML), unknown blocks shown as raw cards, and a committed and embedded bundle with a dist drift gate | ✓ VERIFIED | assets/src/blogeditor/*.ts and toolbar.ts provide H2-H4, bold, italic, lists, link, blockquote, table ops, image, embed and rawHtml. extensions.ts lists the raw block tags (footer, section, aside, details…). admin.go:22 embeds the dist. `check-dist.sh` (diff -r) passes in the gate. Editor vitest 232/232 |
|
||||
| 10 | D-03 (editor and Journal halves) and todo journal-imported-html-admin-resave: an untouched value round-trips byte-identically; Load serves HTML content verbatim and markdown as content_html; an untouched save leaves content and content_html byte-identical | ✓ VERIFIED | The element's `value` getter returns the stored string in clean mode and uses `serializeDocument` (top-level block reuse) only after an edit. It never calls `getHTML`. `loadBlogHTML` implements D-07 plus the CR-01 and WR-04 refinements. element.test.ts, `TestBlogEditorLoad` and `TestFieldTypeUntouched` pass. UAT: post 1 (HTML) and post 64 (markdown) kept the same md5 after untouched saves, and updated_at moved (16.2-05 SUMMARY, follow-up section). The Postgres `TestPostsAdminResaveKeepsHTML` did not run (human item 1) |
|
||||
| 11 | D-02, D-07, D-08, D-09: post content is `mlblogeditor` (excerpt unchanged); an admin save stores the same sanitized HTML in content and content_html per locale without goldmark; the public write API keeps markdown and FormatHTML | ✓ VERIFIED | models/post/fields.yaml: `type: mlblogeditor`, `htmlColumn: content_html`. `preparePostWrite` copies the default-locale write into `ContentHTML`. `writeContentHTMLTranslations` writes non-default locales through `WriteTranslated`. The only remaining FormatHTML callers are the API helpers, the import console and Load's markdown fallback. No migration or column was added. `TestPostsEditorHooks` passes. UAT edit-ok: content = content_html |
|
||||
| 12 | D-10 (amended) and D-05: Decode stores `SanitizeHTMLReport` output and reports removals as notices, never refusing on markup; the policy gains exactly four editor-output rules; every corpus entry passes byte for byte | ✓ VERIFIED | `decodeBlogHTML` and `removalNotices` are in blog_editor.go. Commit 2384a61 adds only `figure data-embed ^youtube$`, `figure data-id ^[A-Za-z0-9_-]{11}$`, `img alt` and `ol start ^[0-9]+$`. `TestEditorOutputPassesPolicy`, `TestSanitizeHTMLReport`, `TestBlogEditorDecode` and `TestBlogEditorNotices` pass. On UAT a style element and an onclick attribute were stripped and the notice was confirmed by the human |
|
||||
| 13 | D-17 and D-05 (layer): `expandEmbeds(sanitizeJournalHtml(html))` at the PostBody and CategoryHeader sinks, with payload transforms only sanitizing; htmlGate mirrors the four rules; corpus copies identical; v0.2.0 tagged and pinned | ✓ VERIFIED | PostBody.vue:13 and CategoryHeader.vue:11 expand last. postView.ts and CategoryPage.vue only sanitize. `expandEmbeds` builds the iframe only from an allowlisted provider, a validated id and a fixed host. `cmp` of the two corpus files is identical. Tag v0.2.0 exists on origin (759e684). The app's package.json pins `#v0.2.0`. Layer 144/144. UAT site-ok found 1 youtube-nocookie iframe |
|
||||
| 14 | D-19 (amended): category content uses blogeditor and is stripped and reported; the 422 CheckHTML gate is retired | ⚠️ PRESENT_BEHAVIOR_UNVERIFIED | models/category/fields.yaml has `type: blogeditor`. `prepareCategoryWrite` only nulls blank content, and no CheckHTML caller remains. The end-to-end category save is covered only by the Docker-only `TestCategoriesAdminContent` and `TestCategoriesAdminBlogEditor` (not run), and the UAT category step was never done |
|
||||
|
||||
**Score:** 13/14 truths verified (1 present, behavior-unverified)
|
||||
|
||||
Release truths from plan 05 are verified separately. Tag v0.1.18 is an annotated tag object 04dc5bd on origin, pointing at commit f1d8a75. The UAT binary sha256 matched the local build, and the on-server smoke passed on 98 URLs. These rest on SUMMARY records; the tag is confirmed directly with `git ls-remote`.
|
||||
|
||||
### Required Artifacts
|
||||
|
||||
| Artifact | Expected | Status | Details |
|
||||
|----------|----------|--------|---------|
|
||||
| `modules/pact/capabilities.go` | FormFieldType family and HasFormFieldTypes | ✓ VERIFIED | All types are present, with Decode, Load, ListValue, Upload and CheckOptions |
|
||||
| `modules/cabana/field_type.go` | registry, compile and the decode/skip/load/list runner | ✓ VERIFIED | 877 lines, substantive, wired from http.go and crud.go |
|
||||
| `modules/cabana/field_type_upload.go` | upload route | ✓ VERIFIED | Mounted at http.go:360 |
|
||||
| `modules/cabana/tx_context.go` | FieldWritesFromContext | ✓ VERIFIED | Consumed by Journal posts.go |
|
||||
| `modules/cabana/relation_field.go` | `notices,omitempty` | ✓ VERIFIED | relation_field.go:99 |
|
||||
| `admin/src/components/form/fields/PluginField.vue` | element host | ✓ VERIFIED | Handles summer-change and summer-upload; passes no token or function to the element |
|
||||
| `admin/src/app/fieldTypes.ts` | global loader | ✓ VERIFIED | Wired in main.ts and LoginView.vue |
|
||||
| `docs/backend/field-types.md` | guide | ✓ VERIFIED | Names HasFormFieldTypes; no consuming application is named |
|
||||
| `../sm-journal-plugin/classes/blog_editor.go` | BlogEditorTypes | ✓ VERIFIED | Registered through field_types.go |
|
||||
| `../sm-journal-plugin/classes/format_html.go` | SanitizeHTMLReport and the four rules | ✓ VERIFIED | |
|
||||
| `../sm-journal-plugin/classes/media_store.go` | StoreMedia | ✓ VERIFIED | Shared with controllers/api/media.go:39 |
|
||||
| `../sm-journal-plugin/assets/dist/blogeditor.js` | committed bundle | ✓ VERIFIED | Embedded at admin.go:22; check-dist passes |
|
||||
| `../sm-journal-plugin/tests/blogeditor/fixtures/editor-corpus.json` | corpus | ✓ VERIFIED | Byte-identical to the layer copy |
|
||||
| `../vue-journal-layer/app/utils/embeds.ts` | expandEmbeds | ✓ VERIFIED | |
|
||||
| `../sm-grzybyfunkcjonalne-app/vue-grzybyfunkcjonalne-app/package.json` | `#v0.2.0` pin | ✓ VERIFIED | |
|
||||
| `modules/cabana/field_type_postgres_test.go` | Postgres test | ✓ EXISTS (not run) | Compiles under go vet; needs Docker |
|
||||
| `scripts/check-phase16.2.sh` | phase gate | ✓ VERIFIED | Re-run in this verification, exit 0 |
|
||||
|
||||
### Key Link Verification
|
||||
|
||||
| From | To | Via | Status |
|
||||
|------|----|-----|--------|
|
||||
| http.go Activate | compileRegistryWithTypes | `compileFieldTypes(plugins)` passed as a parameter | ✓ WIRED |
|
||||
| crud.go save | Decode and Load | `decodePluginFields` between loadRecord and Fill, in the transaction | ✓ WIRED |
|
||||
| crud.go save | meta.notices | `localizeNotices` after commit | ✓ WIRED |
|
||||
| FormView.vue save | FormField notices and toast | `noticeLines(result.data.meta.notices)` | ✓ WIRED |
|
||||
| main.ts / LoginView.vue | GET /field-types | `loadFieldTypes` | ✓ WIRED |
|
||||
| PluginField.vue | upload route | `summer-upload` handled by `api.POST` | ✓ WIRED |
|
||||
| blog_editor.go decodeBlogHTML | SanitizeHTMLReport | direct call | ✓ WIRED |
|
||||
| posts.go preparePostWrite | FieldWritesFromContext | default-locale write sets ContentHTML | ✓ WIRED |
|
||||
| posts.go FormAfterUpdate | TranslationWriter.WriteTranslated | content_html per written locale | ✓ WIRED |
|
||||
| api/media.go UploadMedia | StoreMedia | media.go:39 | ✓ WIRED |
|
||||
| PostBody.vue / CategoryHeader.vue | expandEmbeds | `expandEmbeds(sanitizeJournalHtml(...))` | ✓ WIRED |
|
||||
| admin.go adminFS | assets/dist/blogeditor.js | `//go:embed` | ✓ WIRED |
|
||||
|
||||
### Data-Flow Trace (Level 4)
|
||||
|
||||
| Artifact | Data | Source | Real data | Status |
|
||||
|----------|------|--------|-----------|--------|
|
||||
| PluginField element `value` | form value | Show response from `hydratePluginFields`, which runs Load over the record loaded in the transaction | yes | ✓ FLOWING |
|
||||
| content_html (admin path) | sanitized HTML | Decode output, then FieldWrite, then the hooks | yes (UAT edit-ok shows content = content_html) | ✓ FLOWING |
|
||||
| Site post body | content_html | Journal API, then postView sanitize, then the PostBody sink expandEmbeds | yes (UAT site-ok found the iframe) | ✓ FLOWING |
|
||||
|
||||
### Behavioral Spot-Checks
|
||||
|
||||
| Behavior | Command | Result | Status |
|
||||
|----------|---------|--------|--------|
|
||||
| Full phase gate | `bash scripts/check-phase16.2.sh --all` (TMPDIR in the scratchpad) | self-test, go (19 framework + 29 Journal tests), admin 1218, editor 232, layer 144 plus corpus cmp, and docs all PASS; postgres NOT RUN; "Phase 16.2 gate passed", exit 0 | ✓ PASS |
|
||||
| go vet | `go vet ./...` in summercms.go and sm-journal-plugin | clean | ✓ PASS |
|
||||
| Release tag on origin | `git ls-remote --tags origin v0.1.18` | 04dc5bd, which points at f1d8a75 | ✓ PASS |
|
||||
| Layer tag on origin | `git ls-remote --tags origin` (vue-journal-layer) | v0.2.0, which points at 759e684 | ✓ PASS |
|
||||
| Postgres suites | `check-phase16.2.sh postgres` | no Docker daemon | ? SKIP (human item 1) |
|
||||
|
||||
### Probe Execution
|
||||
|
||||
Step 7c: no `scripts/*/tests/probe-*.sh` is declared or present for this phase. The phase gate above serves as the runnable check.
|
||||
|
||||
### Requirements Coverage
|
||||
|
||||
REQUIREMENTS.md lists no IDs for this phase. The CONTEXT decisions the plans cite:
|
||||
|
||||
| Decision | Status | Evidence |
|
||||
|----------|--------|----------|
|
||||
| D-01, D-04, D-16 | ✓ SATISFIED | Truth 9 |
|
||||
| D-02, D-07, D-08, D-09 | ✓ SATISFIED | Truth 11 |
|
||||
| D-03 | ✓ SATISFIED | Truths 5 and 10 (unit tests plus UAT; Postgres run pending) |
|
||||
| D-05, D-10 | ✓ SATISFIED | Truths 3, 12 and 13 |
|
||||
| D-06, D-14 | ✓ SATISFIED | Truth 6 |
|
||||
| D-11, D-12, D-13, D-15 | ✓ SATISFIED | Truths 1 to 4 and 7 |
|
||||
| D-17 | ✓ SATISFIED | Truth 13 |
|
||||
| D-18 | ✓ SATISFIED | Truth 8 |
|
||||
| D-19 | ? NEEDS HUMAN | Truth 14 |
|
||||
|
||||
### Prohibitions (judgment tier, non-authoritative LLM verdicts)
|
||||
|
||||
| Prohibition | Verdict |
|
||||
|-------------|---------|
|
||||
| No package-level mutable field type registry in cabana | Holds. The only package-level vars are regexes and a static key set. The registry is built per Activate |
|
||||
| The element never receives a token, cookie, function or Vue instance | Holds. PluginField sets only `value` and string attributes; uploads go through `api.POST` |
|
||||
| Core field types, the `type: widget` contract and CompileForm unchanged | Holds as far as the gate shows. TestPhase10CSRF, TestPhase09ContractInventory and ExampleCompileFormWithTypes pass, and settings and relation forms use a refusing registry |
|
||||
| Framework docs name no consuming application | Holds. grep for journal, grzyb, fonoteka and blogeditor in field-types.md, forms.md and the two READMEs finds nothing |
|
||||
| The editor never re-serializes an untouched document or uses getHTML() | Holds. The clean-mode getter returns the stored string |
|
||||
| No eval, no `new Function`, no style injection | Holds. `injectCSS: false`, and no eval in the sources |
|
||||
| The element renders no iframe and no live raw HTML in the admin | **Flagged for human review.** The preview pane folded in from quick 261010-iwu adds a lazily created iframe with an empty `sandbox`, `srcdoc` only and a CSP meta. Raw blocks in the editor itself still render as escaped text |
|
||||
| htmlPolicy gains only the four editor rules; the layer mirrors the same four | Holds. Diff 2384a61 and htmlGate.ts:122-127 |
|
||||
| Public write API and media route keep the PHP contract | Holds. Posts still go through FormatHTML in the API helpers, and media.go keeps its error mapping through MediaError |
|
||||
| No format flag, column or migration | Holds. No migration commit in updates/ during the phase |
|
||||
| Executor ran only SELECTs on UAT; no credentials handled; no tag moved | Taken from the SUMMARY; the tags are unmoved on origin |
|
||||
| Tests not weakened | Taken from the SUMMARY: the 16.1 policy test files are unchanged since c60abc6 |
|
||||
|
||||
### Anti-Patterns Found
|
||||
|
||||
| File | Line | Pattern | Severity | Impact |
|
||||
|------|------|---------|----------|--------|
|
||||
| (none) | | No TBD, FIXME, XXX, TODO or HACK marker in the phase's source files | | |
|
||||
|
||||
Known open review items, skipped by decision (16.2-REVIEW-FIX.md):
|
||||
- WR-07: View site uses the admin origin.
|
||||
- WR-08: the gate passes with postgres NOT RUN; `PHASE162_REQUIRE_POSTGRES=1` enforces it.
|
||||
- IN-01 to IN-03 and IN-05 to IN-08.
|
||||
|
||||
These are information only and do not block.
|
||||
|
||||
### Human Verification Required
|
||||
|
||||
#### 1. Postgres suites on a Docker host
|
||||
|
||||
**Test:** `bash scripts/check-phase16.2.sh postgres`
|
||||
**Expected:** Every named suite passes. This covers WINDOWS 11, 12, 14 to 16, 20 and 21.
|
||||
**Why human:** No Docker on this host. These suites are the only end-to-end proof of the CR-01 and WR-04 Load changes and of the category strip.
|
||||
|
||||
#### 2. D-19 category edit on UAT
|
||||
|
||||
**Test:** Change one word of a category's content in the Blog Editor and save.
|
||||
**Expected:** No removal notice; the site shows the change.
|
||||
**Why human:** WINDOWS 18; never performed.
|
||||
|
||||
#### 3. Re-confirm the untouched resave after the review-fix deploy
|
||||
|
||||
**Test:** After v0.1.19 is deployed, save posts 1 and 64 untouched and re-run the md5 SELECT.
|
||||
**Expected:** The md5 values equal the 16.2-05 snapshot.
|
||||
**Why human:** The UAT proof ran on v0.1.18, before the CR-01 and WR-04 Load changes. The code reading says the outcome is unchanged for these posts.
|
||||
|
||||
#### 4. Preview pane browser check
|
||||
|
||||
**Test:** Check the layout, the sandbox (script in a raw block), the embed card and relative images.
|
||||
**Expected:** As listed in the 261010-iwu SUMMARY.
|
||||
**Why human:** Real browser behaviour.
|
||||
|
||||
#### 5. Accept the preview iframe against the plan 02 prohibition
|
||||
|
||||
**Test:** Decide whether the sandboxed srcdoc preview is an accepted exception to "no iframe in the admin".
|
||||
**Expected:** Accept, or ask for a change.
|
||||
**Why human:** Judgment-tier prohibition.
|
||||
|
||||
### Gaps Summary
|
||||
|
||||
No must-have failed. The framework API (pact.HasFormFieldTypes, the cabana registry, the decode/skip/load/list runner, meta.notices, the upload route), the SPA host, the Journal Blog Editor (element, Go types, policy, hooks, storage) and the layer's embed expansion all exist, are substantive and are wired. The fixed tree passes the phase gate here, and vet is clean in both Go repositories. On UAT (v0.1.18) the goal was proven on real data:
|
||||
- An imported HTML post and a markdown post re-saved untouched with identical md5.
|
||||
- An edited post stored identical content and content_html, with an uploaded figure and a YouTube placeholder.
|
||||
- Disallowed markup was stripped and reported.
|
||||
- The site rendered a youtube-nocookie iframe.
|
||||
|
||||
Status is `human_needed`, not `passed`, for three reasons:
|
||||
- The Docker-only Postgres suites have never run.
|
||||
- The D-19 category path has no executed end-to-end evidence: no Postgres run and no UAT step.
|
||||
- The review fixes (CR-01, WR-01 to WR-06, IN-04) are committed but not deployed or tagged, so the UAT evidence predates them. summercms.go master is 13 commits ahead of origin, and the sm-journal-plugin test and fix commits are not pushed either.
|
||||
|
||||
---
|
||||
|
||||
_Verified: 2026-10-10T17:05:00Z_
|
||||
_Verifier: Claude (msd-verifier)_
|
||||
Reference in New Issue
Block a user