22 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 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 11.2-ready-to-share-summercms-io-website-and-newsletter-plugin | 02 | infra |
|
|
|
|
|
130b6ac38f |
a494375db7 |
|
|
|
|
|
22min | 2026-10-01 | complete |
Phase 11.2 Plan 02: summercms.io app, site plugin, release path and deploy Summary
One summercms-io binary that embeds the Nuxt landing page and the SummerCMS docs. It serves them on PostgreSQL 15 with indexable, cache-correct responses. The framework gained PG15 docs and a docs header link back to the site. The release build is proven from a (scratch) v0.1.0 tag, every landing link and terminal command is checked against the built site, and DEPLOY.md covers rome.
Performance
- Duration: 22 min (two executor sessions: tasks 1-2, then the tag checkpoint, then tasks 4-5)
- Started: 2026-10-01T14:00:22Z
- Completed: 2026-10-01T14:22:03Z
- Tasks: 5 (4 auto/tracer, 1 decision checkpoint)
- Files modified: 10 in summercms.go, 26 in sm-summercmsio-app plus plugin (excluding generated build output)
Accomplishments
- Site plugin
golem15.summercms(modulegit.golem15.com/golem15/sm-summercmsio-plugin). It embedspublic/withall:and serves/and/docsfrom in-memory trees with these behaviours:- strong ETags with 304 revalidation;
immutablecaching for_nuxt/(exceptbuilds/) and_fonts/, andno-cachefor everything else;- a 301 from extension-less docs URLs to
.html; - the tree's own 404 page, and dot-segment paths refused;
- no robots-blocking header, no CSP and no admin.
- App
sm-summercmsio-appis a go.work workspace with the plugin and site as submodules, config without secrets,summer buildgenerated sources, and these scripts:scripts/build.sh, with release (default, from the tag) and dev modes;scripts/smoke.sh, which runs postgres:15, migrate, serve and HTTP assertions, including the D-46 docs header link;scripts/check-deploy.sh.
- Framework (summercms.go):
- The PG15 suites pass, and README.md and docs/setup/installation.md say "PostgreSQL 15 or newer".
docs/site.yamlaccepts thesite_urlandsite_labelkeys, anddocs:buildanddocs:servetake--site-urland--site-label. Both are validated:javascript:and//hostare rejected.
- Checks:
TestLandingLinkschecks 30 distinct links through the realsurf.Assemblehandler, including all ten D-44 docs targets and/docs.TestTerminalCommandsInPageis the D-40 drift guard.TestDocsHeaderSiteLinkchecks the docs header link back to/.TestExternalLinksruns at cutover.TestTerminalCommandsruns the six page commands from a fresh shell tohandled=true.
- DEPLOY.md covers the launch checklist, server setup, build, upload, release, cutover, verification and rollback. It comes with the nginx config (HTTP→HTTPS, a 443 www→apex block, gzip,
/backenddenied, GET/HEAD only, proxy to 127.0.0.1:8095), the supervisor program, an env template and a copy of the live "Under construction" page.
Task Commits
| Task | Commit | Repo | Message |
|---|---|---|---|
| 1 (tracer) | 0ab96ed |
sm-summercmsio-plugin | feat: serve the embedded site at / and the docs at /docs |
| 1 (tracer) | e0b9b7c |
sm-summercmsio-app | feat: wire the summercms.io app with build and smoke scripts |
| 2A | 7936234 |
summercms.go | docs: require PostgreSQL 15 or newer (verified on postgres:15) |
| 2B | a494375 |
summercms.go | feat(docsite): optional site_url and site_label link back to the main site |
| 3 | — | — | decision checkpoint, resolved defer-tag (no commit) |
| 4 | 7774763 |
sm-summercmsio-plugin | test: verify the landing links and terminal commands against the built site |
| 4 | 699785a |
sm-summercmsio-app | feat: release builds from the v0.1.0 tag and the terminal command check |
| 5 | fe77fa7 |
sm-summercmsio-plugin | docs: describe the site plugin |
| 5 | 77eef5d |
sm-summercmsio-app | docs: add DEPLOY.md with nginx, supervisor and rollback configs |
Each app commit carries the updated plugin gitlink. Nothing was pushed anywhere, and no commit has a co-author trailer.
D-42 tag decision: defer-tag
- What the user chose: "defer-tag" at the blocking-human checkpoint (Task 3).
- summercms.go is untouched:
git tag -l v0.1.0in summercms.go prints nothing, and nothing was pushed. - How the release path was proven: against the scratch clone
/tmp/claude-1000/-media-nvme-dev-golem15-summercms-io-summercms-summercms-go/b0d2a3f5-592c-4ca7-8d0c-8f89dbb2cfac/scratchpad/fw-release. That clone is agit cloneof the local summercms.go with a local annotatedv0.1.0tag ata494375(the Task 2 docsite commit). The build ran asSUMMERCMS_FRAMEWORK=<clone> scripts/build.sh. - Release build output:
build: bin/summercms-io (release v0.1.0) ready.go version -m bin/summercms-ioshowsdep git.golem15.com/golem15/summercms v0.1.0 => /tmp/…/fw (devel), so the compiled framework is the tag export. - Without the tag: plain
scripts/build.shagainst the real checkout stops withbuild: tag v0.1.0 not found in …/summercms.go; run 'scripts/build.sh dev' or create the tag (DEPLOY.md). - Launch checklist step 3 in DEPLOY.md:
- Review the commit.
git tag -a v0.1.0 -m "SummerCMS Alpha 0.1" <reviewed-sha>.git push origin master.git push origin v0.1.0.- Confirm with
git ls-remote --tags origin v0.1.0.
Verification Evidence
D-25, PostgreSQL 15 (previous session).
- Setup: HEAD export, with
postgres:16-alpinereplaced bypostgres:15in 9 test files, run asgo test -count=1 -p 4 -v. - Result: EXIT=0, and all 11 containers were postgres:15 (log:
scratchpad/pg15.log). - Packages, every line
ok, noFAIL:- modules:
lagoon53.2s,lagoon/attach66.9s,cabana65.6s,beachcomber44.4s,beachcomber/typesense0.2s,lighthouse22.2s,lighthouse/centrifugo0.1s,bouncer8.0s,conga19.7s; - docs/examples:
blog5.5s,blog/console,blog/controllers,blog/models,blog/updates.
- modules:
Task 1 tracer gate (previous session). scripts/build.sh dev and scripts/smoke.sh ("smoke: ok") passed, go vet was clean in the app and the plugin, and TestStaticSmoke passed. All Task 1 acceptance criteria passed.
Task 2.
go vet ./...is clean.- The six named tests pass: TestDocsTree, TestDocsBuildRealTree, TestToolCommandNames, TestParseSite, TestSiteLink and TestDocsBuildSiteFlags.
scripts/check-phase11.1.sh --docsand--forbiddenpass.- Re-run at the end of this session:
go vet ./... && go test ./internal/docsite ./cmd/summer -count=1ok, and both phase11.1 checks passed.
Task 4.
- Release build: see the D-42 section above.
scripts/smoke.sh→smoke: ok, with the new D-46/docs/site-link assertions.SUMMERCMS_REQUIRE_BUILD=1 go test ./...in the plugin: PASS for TestLandingLinks, TestTerminalCommandsInPage, TestDocsHeaderSiteLink and TestStaticSmoke; TestExternalLinks SKIP (it is gated).SUMMERCMS_TERMINAL_CHECK=1 SUMMERCMS_CLONE_URL=…/summercms.go go test -run TestTerminalCommands: PASS. The output includedbuilt hello in 1.93s,golem15.greeter activeand… handled=true.grep -c 'class="site-link" href="/"' public/docs/index.html= 1.go vet ./...andgo test ./... -count=1pass in the app (gated tests skip).file bin/summercms-io: ELF 64-bit x86-64, statically linked.
Task 5.
scripts/check-deploy.sh→check-deploy: ok. It runsnginx -ton nginx 1.30.4 with a temp self-signed certificate, temp DH parameters and loopback ports. The only output is deprecation warnings forlisten … http2, which is kept for rome's assumed nginx 1.22, per A3.- All acceptance greps match.
git ls-fileslists no.env.
Files Created/Modified
summercms.go (Task 2, previous session)
README.mdanddocs/setup/installation.md: PostgreSQL 15 or newer.internal/docsite/{load,docsite,emit}.go,theme/templates/header.html,theme/assets/site.css: thesite_url/site_labellink.cmd/summer/docs.go: the flags.docs/console/utilities.md: the docs, with a neutralacme.exampleexample.- Tests in
load_test.go,theme_test.goandcmd/summer/docs_test.go.
sm-summercmsio-plugin
plugin.go,static.go,smoke_test.go,go.mod/go.sum,.gitignore,public/README.md(Task 1).links_test.go(Task 4) andREADME.md(Task 5).
sm-summercmsio-app
- Workspace, config, generated sources and submodules (Task 1).
scripts/build.sh: release mode.scripts/smoke.sh: D-46 assertion.terminal_check_test.go(Task 4).DEPLOY.md,README.md,deploy/**,scripts/check-deploy.sh(Task 5).
Decisions Made
- D-42: defer-tag (user decision). See the section above.
- Clone override in
terminalScript. A non-emptySUMMERCMS_CLONE_URLbecomesgit clone <override> summercms, with the directory taken frompath.Baseof the page URL. The page's next command,cd summercms, then works for a local override such as…/summercms.go. With no override, the commands run verbatim. check-deploy.shtest copy. It rewrites the listen ports to127.0.0.1:18480/[::1]:18480and127.0.0.1:18443/[::1]:18443(overridable), becausenginx -tbinds the listeners and a non-root check cannot bind 80 or 443. The committed config keeps 80 and 443.- DEPLOY.md choices:
bin/andconfig/are root-owned, so the service cannot rewrite its own binary;storage/is owned by summercms.- Uploads use
--rsync-path="sudo rsync". - The supervisor program is installed on the first release, because autostart before the binary exists would put the program into FATAL.
- The key comes from
./bin/summercms-io key:generate, which prints✓ <key>.
TestLandingLinksscope. It also checkssrclinks,_payload.json?<uuid>and the og:image (https://summercms.io/og-image.pngmapped to/og-image.png), not only hrefs.
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] The terminal check's clone override changed the clone directory
- Found during: Task 4.
- Issue:
git clone /…/summercms.goclones intosummercms.go/, so the page's next command,cd summercms, failed (cd: summercms: No such file or directory). - Fix: with an override,
terminalScriptpasses the page URL's directory name explicitly (git clone <override> summercms). The verbatim run (no override) is unchanged. - Files modified:
sm-summercmsio-app/terminal_check_test.go. - Verification: TestTerminalCommands PASS with handled=true.
- Committed in:
699785a.
2. [Rule 3 - Blocking] nginx -t binds the listen ports
- Found during: Task 5.
- Issue: As a normal user,
nginx -tfailed withbind() to 0.0.0.0:80 failed (13: Permission denied). - Fix:
check-deploy.shrewrites the listen directives in its temp copy to unprivileged loopback ports, and fails if any 80/443 listen remains unreplaced. The DH parameters are generated withopenssl dhparam -dsaparaminstead of dropping thessl_dhparamline. - Files modified:
sm-summercmsio-app/scripts/check-deploy.sh. - Verification:
check-deploy: ok. Earlier, a failing run showed the script surfaces nginx errors. - Committed in:
77eef5d.
3. [Rule 1 - Bug, previous session] checkSiteURL also rejects backslashes
- Issue: browsers treat
/\hostas//host, which would make a protocol-relative link to another host. - Fix: backslashes are rejected, and
--site-labelis validated as one non-empty line. The override logic lives inload()inload.go. - Committed in:
a494375.
4. [Rule 3 - Blocking, previous session] summer plugin:add wrote an absolute path into the go.work use list
- Fix: rewritten to
./plugins/golem15/summercmswithgo work edit.go mod tidybefore the firstsummer builddropped the requires: they were restored, the build ran, the module was tidied, andtoolchain go1.27.0was re-added. - Follow-up: the framework quirks are logged in
deferred-items.md. - Committed in:
e0b9b7c.
5. [Acceptance-check note, previous session] Task 2 byte-identical check
- Issue: a literal
diff -r pre postcannot be empty, because the content ofutilities.mdchanged and the.site-linkrules live in the sharedassets/site.css. - Isolated check: the pre-change docs source was built with the new binary. Only
assets/site.cssdiffers, by 17 additive lines. All 72 HTML pages, the.mdcopies,llms*.txtandsearch-index.jsonare byte-identical. An unset build has 0site-linkinindex.htmland404.html.
6. [Acceptance-check note] The location ^~ /backend grep
- Issue: the plan's literal
grep -n 'location ^~ /backend'cannot match, because GNU BRE treats the mid-pattern^as an anchor. - Check:
grep -nF 'location ^~ /backend'matches line 50 ofdeploy/nginx/summercms.io.conf.
Total deviations: 4 auto-fixed (2 bugs, 2 blocking) and 2 acceptance-check notes. Impact on plan: All fixes were needed for the checks to run as specified. There was no scope creep, and no new Go module or npm dependency.
Issues Encountered
- HEAD on
master. The executor's protected-branch assertion reportsmasteras protected. This project commits directly on master (branching_strategynone, use_worktreesfalse), and the sequential orchestrator dispatch said to use normal commits on the main working tree, as the previous session did for7936234anda494375. Commits were made on master, and none were pushed. - Generated build output.
bin/summercms-ioandplugins/golem15/summercms/public/{site,docs}now hold a release build from the scratch tag. These paths are gitignored.
Known Stubs
None. The gated tests (TestExternalLinks, and TestTerminalCommands without an override) are designed to run at cutover, not stubs.
Threat Flags
None beyond the plan's threat model. T-11.2-04/05/06/07/08/09/11/12/14 are mitigated as planned. T-11.2-13 (the tag) is deferred to the user at cutover.
User Setup Required
These are the cutover steps from the DEPLOY.md launch checklist, all for the user:
- Push
sm-summercmsio-plugin,vue-summercmsio-app, thensm-summercmsio-app. The origins are already set. - Make
golem15/summercmspublic (D-38). - Create
v0.1.0ofgit.golem15.com/golem15/summercmsat the reviewed commit, push it, and push summercms.gomaster(D-42, deferred). - Run
TestExternalLinksand the verbatimTestTerminalCommands. - On rome: check that port 8095 is free, do the one-time setup, save the existing summercms.io server block into
deploy/rollback/nginx-under-construction.conf, then deploy and cut over.
Next Phase Readiness
- Plan 11.2-03 (unit test coverage) can build on the stable interfaces:
Plugin,newHandlers,tree,newTree,contentType,siteImmutable,redirectTo,pageLinks,resolve,requireBuild,terminalScript,terminalEnv,loadTerminal,checkSiteURLandsiteLabel. - The cutover is blocked only on the user steps above.
Self-Check: PASSED
- Files exist: plugin.go, static.go, links_test.go and README.md in the plugin; build.sh, smoke.sh, check-deploy.sh, terminal_check_test.go, DEPLOY.md, README.md, the deploy/nginx and deploy/supervisor configs, deploy/env.example and deploy/rollback/under-construction/{index.html,logo.png} in the app.
- Commits found:
0ab96ed,7774763andfe77fa7(plugin);e0b9b7c,699785aand77eef5d(app);7936234anda494375(summercms.go). - No
v0.1.0tag in summercms.go, and nothing pushed.
Phase: 11.2-ready-to-share-summercms-io-website-and-newsletter-plugin Completed: 2026-10-01