From d3b1636ac772d1cd2bacd585304fb1ab800ebb88 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Mon, 26 Oct 2026 13:47:45 +0100 Subject: [PATCH] docs(19.6-03): complete WebAuthn and adoption plan sm-demo-app mounts golem15.mfa v0.1.0 at user v0.1.12, sociallogin v0.1.4 and the two-factor UI (0eb1f60..bb24207, pushed with the 19 earlier commits as 18597e5..bb24207, not deployed). The summary records the "proceed" reply, the push checks and the tests. deferred-items.md gains the private sm-mfa-plugin repository's effect on the demo's release build, and a pending todo tracks the demo's leftover journal and oauthserver moves. --- .../19.6-03-SUMMARY.md | 240 +++++++++++++----- .../deferred-items.md | 6 + ...m-demo-app-journal-oauthserver-pointers.md | 15 ++ 3 files changed, 197 insertions(+), 64 deletions(-) create mode 100644 .planning/todos/pending/2026-10-26-sm-demo-app-journal-oauthserver-pointers.md diff --git a/.planning/phases/19.6-two-factor-auth-and-device-flow-in-sm-user-plugin/19.6-03-SUMMARY.md b/.planning/phases/19.6-two-factor-auth-and-device-flow-in-sm-user-plugin/19.6-03-SUMMARY.md index b68ac1d8..ac90849d 100644 --- a/.planning/phases/19.6-two-factor-auth-and-device-flow-in-sm-user-plugin/19.6-03-SUMMARY.md +++ b/.planning/phases/19.6-two-factor-auth-and-device-flow-in-sm-user-plugin/19.6-03-SUMMARY.md @@ -2,7 +2,7 @@ phase: 19.6-two-factor-auth-and-device-flow-in-sm-user-plugin plan: 03 subsystem: auth -tags: [sm-mfa-plugin, webauthn, go-webauthn, passkeys, passwordless, sm-sociallogin-plugin, login-gate, vue-demo-app, totp-ui, release, draft] +tags: [sm-mfa-plugin, webauthn, go-webauthn, passkeys, passwordless, sm-sociallogin-plugin, login-gate, vue-demo-app, totp-ui, release, sm-demo-app, sm-bm-app] requires: - phase: 19.6-01 @@ -16,22 +16,23 @@ provides: - D-09 social-login gate in sm-sociallogin-plugin v0.1.4 - Demo two-factor UI in vue-demo-app (TOTP setup, recovery codes, disable, login challenge; D-20), pushed - Releases: sm-user-plugin v0.1.12, sm-mfa-plugin v0.1.0 (new private repository), sm-sociallogin-plugin v0.1.4 + - sm-demo-app mounts golem15.mfa v0.1.0 at user v0.1.12, sociallogin v0.1.4 and the two-factor UI, pushed (not deployed) - sm-bm-app mounts golem15.mfa (API only) at user v0.1.12 and sociallogin v0.1.4, pushed - fonoteka.go at sm-user-plugin v0.1.12 with its guard tests updated (local commit) affects: [19.6-04, sm-demo-app, sm-bm-app, fonoteka.go, vue-demo-app, sm-sociallogin-plugin] actuals: - tokens: 37360 # MEASURED chars/4 over added lines: Tasks 1-3 35354, plus 33ad164, b752177, sm-bm-app aafbcce..ebb2266, fonoteka.go 06bc9d0..95fd58a (go.sum and go.work.sum excluded) - tasks: 5 # Tasks 1-5 done; Task 6 parts (2) and (3) done, part (1) sm-demo-app open at a checkpoint - commits: 0 # MEASURED in summercms.go before this draft's commit: git rev-list --count 5a64611..HEAD (code lives in other repositories) + tokens: 38817 # MEASURED chars/4 over added lines: 37360 at the draft (Tasks 1-3, 33ad164, b752177, sm-bm-app aafbcce..ebb2266, fonoteka.go 06bc9d0..95fd58a) plus sm-demo-app 40ed518..bb24207 (5827 chars); go.sum and go.work.sum excluded + tasks: 6 + commits: 2 # MEASURED in summercms.go before this final commit: git rev-list --count 5d78f53..HEAD (5a64611, 4002bea); this SUMMARY commit and the ROADMAP commit follow. Code lives in other repositories (below) sm_mfa_plugin_commits: 3 # MEASURED: git -C ../sm-mfa-plugin rev-list --count 8a63f6f..HEAD sm_sociallogin_plugin_commits: 2 # MEASURED: git -C ../sm-sociallogin-plugin rev-list --count 4d3b2dd..HEAD vue_demo_app_commits: 1 # MEASURED: git -C ../sm-demo-app/vue-demo-app rev-list --count 9c247ab..HEAD sm_bm_app_commits: 3 # MEASURED: git -C ../sm-bm-app rev-list --count aafbcce..HEAD fonoteka_go_commits: 1 # MEASURED: git -C ../fonoteka.go rev-list --count 06bc9d0..HEAD - sm_demo_app_commits: 0 # Task 6 part (1) not started (checkpoint) + sm_demo_app_commits: 4 # MEASURED: git -C ../sm-demo-app rev-list --count 40ed518..bb24207 plan_head_before: 5d78f53ddc890ef53fe52da1828f3f88d9923270 -plan_head_after: 5a64611 +plan_head_after: 4002bea sm_mfa_plugin_head_before: 8a63f6f sm_mfa_plugin_head_after: 33ad164 sm_sociallogin_plugin_head_before: 4d3b2dd @@ -42,16 +43,18 @@ sm_bm_app_head_before: aafbcce sm_bm_app_head_after: ebb2266 fonoteka_go_head_before: 06bc9d0 fonoteka_go_head_after: 95fd58a +sm_demo_app_head_before: 40ed518 +sm_demo_app_head_after: bb24207 sm_user_plugin_head: 3b22134 # tagged v0.1.12 and pushed tech-stack: added: - - "github.com/go-webauthn/webauthn v0.18.2 (packages webauthn, protocol), sm-mfa-plugin only (approved 2026-10-26); brings fxamacker/cbor/v2, go-webauthn/x, google/go-tpm, tinylib/msgp as indirect modules (also indirect in sm-bm-app through the mount)" + - "github.com/go-webauthn/webauthn v0.18.2 (packages webauthn, protocol), sm-mfa-plugin only (approved 2026-10-26); brings fxamacker/cbor/v2, go-webauthn/x, google/go-tpm, tinylib/msgp as indirect modules (also indirect in sm-bm-app and sm-demo-app through the mount)" patterns: - "WebAuthn ceremony state server-side: registration and passkey state in cooler consumed with Pull; login state on the challenge row" - "Pure verification helpers (VerifyRegistration, VerifyAssertion) shared by handlers and a no-database smoke test" - "Virtual authenticator test helper (ECDSA P-256, attestation none, CBOR through go-webauthn's webauthncbor)" - - "Application mount test without a database: route table entry with the owning plugin, a compiled handler, and an anonymous request refused by jwt.auth (sm-bm-app TestMFAMounted)" + - "Application mount test without a database: route table entry with the owning plugin, a compiled handler, and an anonymous request refused by jwt.auth (TestMFAMounted in sm-bm-app and sm-demo-app)" key-files: created: @@ -70,16 +73,21 @@ key-files: - ../sm-demo-app/vue-demo-app/app/lib/twoFactor.test.ts - ../sm-demo-app/vue-demo-app/app/composables/useTwoFactor.ts - ../sm-demo-app/vue-demo-app/app/pages/account/security.vue + - ../sm-demo-app/mfa_test.go + - ../sm-demo-app/config/golem15.mfa.yaml + - ../sm-demo-app/plugins/golem15/mfa (submodule) - ../sm-bm-app/mfa_test.go - ../sm-bm-app/plugins/golem15/mfa (submodule) - .planning/phases/19.6-two-factor-auth-and-device-flow-in-sm-user-plugin/19.6-03-sociallogin-gate.patch - .planning/phases/19.6-two-factor-auth-and-device-flow-in-sm-user-plugin/deferred-items.md + - .planning/todos/pending/2026-10-26-sm-demo-app-journal-oauthserver-pointers.md modified: - ../sm-mfa-plugin/{go.mod,go.sum,routes.go,plugin.go,README.md,config/config.yaml,lang/en/lang.yaml,lang/pl/lang.yaml} - ../sm-mfa-plugin/classes/{config.go,methods.go,admin.go,events.go,login.go} - ../sm-sociallogin-plugin/{classes/flow.go,classes/codes.go,controllers/callback.go,controllers/complete.go,controllers/register_complete.go,lang/en/lang.yaml,lang/pl/lang.yaml,README.md,go.mod,go.sum} - ../sm-demo-app/vue-demo-app/app/{composables/useDemoAuth.ts,pages/login.vue,components/SiteHeader.vue} - ../sm-demo-app/vue-demo-app/i18n/locales/{en.json,pl.json} + - ../sm-demo-app/{.gitmodules,go.mod,go.sum,go.work,summer.yaml,plugins.gen.go,boot_test.go,deploy/env.example,README.md,plugins/golem15/user,plugins/golem15/sociallogin,vue-demo-app} - ../sm-bm-app/{.gitmodules,go.mod,go.sum,go.work,summer.yaml,plugins.gen.go,scripts/build.sh,README.md,plugins/golem15/user,plugins/golem15/sociallogin} - ../fonoteka.go/{plugins/golem15/user,parity/migrate_test.go,parity/schema_diff_test.go,plugins/golem15/fonoteka/classes/hidden_marshal_test.go,plugins/golem15/fonoteka/phase07_coverage_test.go,plugins/golem15/fonoteka/routes_isolation_test.go} @@ -93,11 +101,12 @@ key-decisions: - "No framework tag: sm-mfa-plugin and sm-sociallogin-plugin pass against the framework's v0.5.0 tag; sociallogin's require rose from v0.3.1 to v0.5.0 through go mod tidy" - "Release tags: sm-user-plugin v0.1.12, sm-mfa-plugin v0.1.0, sm-sociallogin-plugin v0.1.4 (the plan's v0.1.6 and v0.1.3 were stale)" - "fonoteka.go guard tests follow the user plugin across every version the bump crosses (v0.1.10 to v0.1.12), not only this phase's additions, because they were already red at the committed v0.1.10 pointer" + - "sm-demo-app's golem15.mfa config: two_factor_mode optional, methods [totp, email], social sign-ins unchallenged (the demo's OAuth callback page does not handle two_factor_required), webauthn not offered (no demo screens); RP defaults to the app.url host, which is demo.summercms.io in production" patterns-established: - "Plugin work in a checkout the executor cannot write: implement and test in a scratch clone with a GOWORK file, export git format-patch, keep the patch in the phase directory, apply with git am once access is granted and verify the tree hash matches" -requirements-completed: [] # draft; the plan's requirements are copied when the plan completes after Task 6 part (1) +requirements-completed: [SC-1, SC-2, SC-4, D-01, D-02, D-04, D-05, D-06, D-08, D-09, D-10, D-14, D-16, D-17, D-19, D-20] coverage: - id: D1 @@ -137,46 +146,52 @@ coverage: - kind: other ref: "pnpm build; server render of /account/security and /login on the built output (200)" status: pass + - kind: integration + ref: "../sm-demo-app/mfa_test.go#TestMFAMounted (the API the screens call is mounted in the demo)" + status: pass human_judgment: true - rationale: "Look and flow in a browser against a running demo with golem15.mfa mounted are a visual judgement; the demo mount (Task 6 part 1) is open at the checkpoint." + rationale: "Look and flow in a browser against a running demo with golem15.mfa mounted are a visual judgement; no browser run was made and the demo is not deployed." - id: D5 - description: "D-17 adoption: plugins published in order; bm mounts mfa; fonoteka.go green at the new pointer without mfa; demo mount pending" + description: "D-17 adoption: plugins published in order; demo and bm mount mfa; fonoteka.go green at the new pointer without mfa" requirement: "D-17" verification: - kind: other - ref: "ls-remote of v0.1.12, v0.1.0, v0.1.4 and the pushed branches; sm-bm-app TestMFAMounted; fonoteka.go vet, -short suites and build" + ref: "ls-remote of v0.1.12, v0.1.0, v0.1.4 and the pushed branches; sm-bm-app TestMFAMounted; sm-demo-app TestMFAMounted, TestBootAllPlugins, TestGoModRequiresTags and the full suite; fonoteka.go vet, -short suites and build" status: pass - human_judgment: true - rationale: "sm-demo-app part is waiting on the user's decision about another session's uncommitted user pointer." + human_judgment: false -duration: 75min +duration: about 100 min of wall clock (2026-10-26 11:08Z to 12:50Z), including two checkpoint waits completed: 2026-10-26 -status: draft +status: complete --- -# Phase 19.6 Plan 03: WebAuthn and adoption Summary (draft) +# Phase 19.6 Plan 03: WebAuthn and adoption Summary -**Status:** draft at a second checkpoint, during Task 6 part (1). -- **Done:** - - Tasks 1-5. - - Task 6 part (2), sm-bm-app: committed and pushed. - - Task 6 part (3), fonoteka.go: committed locally, not pushed. -- **Not started:** Task 6 part (1), sm-demo-app. Another session's uncommitted edit moved its `plugins/golem15/user` pointer to v0.1.11, and the plan says to stop when another session's edits touch a Task 6 file. See "Open checkpoint". +**WebAuthn second factor and passwordless passkeys in sm-mfa-plugin v0.1.0 (go-webauthn v0.18.2, ceremony state server-side), the social-login gate in sm-sociallogin-plugin v0.1.4, the demo's TOTP screens, and adoption in sm-demo-app, sm-bm-app (both pushed) and fonoteka.go (local).** + +**Status:** complete. All 6 tasks are done. +- **sm-demo-app (Task 6 part 1):** commits A-D made and pushed, after the second checkpoint was resolved (see "Task 6 sm-demo-app reply"). +- **sm-bm-app (part 2):** pushed. +- **fonoteka.go (part 3):** local commit only. + +Nothing was deployed. **Results:** -- **sm-mfa-plugin v0.1.0:** WebAuthn security keys as a second factor (go-webauthn v0.18.2, ceremony state server-side) and passwordless passkey sign-in behind its setting. The new private repository is https://git.golem15.com/golem15/sm-mfa-plugin. +- **sm-mfa-plugin v0.1.0:** WebAuthn security keys as a second factor and passwordless passkey sign-in behind its setting. The new private repository is https://git.golem15.com/golem15/sm-mfa-plugin. - **sm-sociallogin-plugin v0.1.4:** social sign-in goes through the login gate (D-09). - **sm-user-plugin v0.1.12:** plan 01's login gates and device authorization, published. - **vue-demo-app:** the TOTP setup, recovery-code and login-challenge screens are pushed. -- **sm-bm-app:** mounts golem15.mfa (API only), with user v0.1.12 and sociallogin v0.1.4. Pushed. +- **sm-demo-app:** mounts golem15.mfa v0.1.0 with user v0.1.12, sociallogin v0.1.4 and the two-factor UI. Pushed, not deployed. +- **sm-bm-app:** mounts golem15.mfa (API only) with user v0.1.12 and sociallogin v0.1.4. Pushed. - **fonoteka.go:** at user v0.1.12, guard tests updated. Local commit only. ## Performance - **Started:** about 2026-10-26T11:08Z -- **First checkpoint:** 2026-10-26T11:48Z -- **Continuation:** about 11:55Z to 12:25Z -- **Tasks:** 5 of 6, with Task 6 partly done. +- **First checkpoint (Task 4):** 11:48Z +- **First continuation:** about 11:55Z to 12:25Z, ending at the second checkpoint (sm-demo-app) +- **Second continuation:** about 12:30Z to 12:50Z +- **Tasks:** 6 of 6 ## Task 4 reply @@ -191,8 +206,8 @@ The orchestrator's interpretation, recorded as given: - Pushing vue-demo-app is authorised, including the 4 unpushed Phase 19.7 commits (`0125e29`, `b973a76`, `3c53182`, `9c247ab`) under `44a5229`. - Pushing sm-demo-app after Task 6's commits is authorised, including its 19 unpushed commits from other phases. - sm-bm-app may be pushed after Task 6 only if its unpushed range is this phase's commits. - - Never stage another session's uncommitted edits. sm-demo-app has another session's uncommitted journal, oauthserver and user pointer moves; leave them. sm-bm-app has dirty planning files; leave them too. -3. **Ownership:** the orchestrator ran `sudo chown -R golem:golem` on `sm-sociallogin-plugin`. It is now golem-owned, clean, at `4d3b2dd` (v0.1.3). No other sudo. + - Never stage another session's uncommitted edits. +3. **Ownership:** the orchestrator ran `sudo chown -R golem:golem` on `sm-sociallogin-plugin`. No other sudo. Further limits: - **Plan 04 patch tags:** not authorised. Plan 04 must ask again before any tag. @@ -200,6 +215,33 @@ Further limits: - fonoteka.go is never pushed. - No framework tag and no changelog post. +## Task 6 sm-demo-app reply + +**Context:** the first continuation stopped before Task 6 part (1). sm-demo-app had uncommitted submodule pointer moves: +- journal `4ab94da`→`b129902` +- oauthserver `8bbec72`→`b6a9586` +- user `bfcfea4`→`50da92c` (v0.1.11) +- vue-demo-app `9c247ab`→`44a5229` (this phase's) + +Commit A has to move that same user pointer. The orchestrator investigated: the moves are leftover Phase 19.7 checkouts (plan 05, 2026-10-23) that were never committed into sm-demo-app, not a live session. + +The user's reply, verbatim: "proceed" + +The orchestrator's interpretation, recorded as given: +- Move only the demo's `plugins/golem15/user` checkout from `50da92c` (v0.1.11) to v0.1.12 (`3b22134`), and make commits A-D as the plan specifies: + - A: user v0.1.12 + - B: sociallogin v0.1.4 + - C: mount golem15.mfa at v0.1.0 as the submodule `plugins/golem15/mfa` + - D: the vue-demo-app pointer to `44a5229` +- Leave the journal and oauthserver moves unstaged and untouched. +- Run the demo verify (`TestMFAMounted`, `TestBootAllPlugins`, `TestGoModRequiresTags`, plus vet, `-short` and the full suite as the plan says). +- Push sm-demo-app master. The authorised range is the 19 pre-existing unpushed commits (`a25444e..40ed518`, all dated 2026-10-23) plus A-D. Fetch first and verify the unpushed range is exactly those; if origin moved or anything else appears, stop and return a checkpoint. +- No force-push, no deploy. Plan 04 patch tags remain not authorised. + +**Outcome:** +- **User checkout:** fast-forwarded on its `master` branch from `50da92c` to `3b22134`. `50da92c` is an ancestor and is on origin, and the submodule tree was clean. +- **journal and oauthserver:** left as they were (still ` M`). They are tracked as a pending todo. + ## Commits per repository | Task | Repository | Commit | Message | @@ -210,11 +252,31 @@ Further limits: | 3 | vue-demo-app | `44a5229` | feat: two-factor setup and the login challenge | | 5 | sm-mfa-plugin | `33ad164` | chore: require sm-user-plugin v0.1.12 | | 5 | sm-sociallogin-plugin | `b752177` | chore: require sm-user-plugin v0.1.12 | +| 6 (1) A | sm-demo-app | `0eb1f60` | chore: bump sm-user-plugin to v0.1.12 and require summercms v0.5.0 | +| 6 (1) B | sm-demo-app | `1c43e29` | chore: bump sm-sociallogin-plugin to v0.1.4 | +| 6 (1) C | sm-demo-app | `2e5b7da` | feat: mount golem15.mfa | +| 6 (1) D | sm-demo-app | `bb24207` | chore: bump vue-demo-app to the two-factor UI | | 6 (2) | sm-bm-app | `aad6004` | chore: bump sm-user-plugin to v0.1.12 | | 6 (2) | sm-bm-app | `376cff4` | chore: bump sm-sociallogin-plugin to v0.1.4 | | 6 (2) | sm-bm-app | `ebb2266` | feat: mount golem15.mfa | | 6 (3) | fonoteka.go (local only) | `95fd58a` | chore: bump sm-user-plugin to v0.1.12 | | draft | summercms.go | `5a64611` | docs(19.6-03): draft summary at the Task 4 release checkpoint | +| draft | summercms.go | `4002bea` | docs(19.6-03): release and adoption up to the sm-demo-app checkpoint | + +What commit C (`2e5b7da`) changes: +- **Mount:** + - `.gitmodules`, with the submodule `plugins/golem15/mfa` at v0.1.0 (`33ad164`) + - `go.work`: `use ./plugins/golem15/mfa` + - `summer.yaml`: `golem15.mfa` after `golem15.sociallogin` + - `go.mod`: require v0.1.0, tidied + - `plugins.gen.go`: regenerated by `summer build`, the only file it changed (main.go was unchanged) +- **Config and docs:** + - `config/golem15.mfa.yaml` + - `deploy/env.example`, with commented `SUMMER_GOLEM15__MFA__` lines + - the README plugin row +- **Tests:** + - `boot_test.go`: `wantPlugins` and the `/_user/api/v1/2fa/` and `/_user/api/v1/devices` prefixes + - new `mfa_test.go` ## Remote operations (in order) @@ -225,7 +287,6 @@ Before every push I ran `git fetch` and checked that `origin/master..master` hel - Annotated tag **v0.1.12** on `3b22134` (tag object `c0e0e85`), pushed. 2. **sm-mfa-plugin:** - Created the private repository **https://git.golem15.com/golem15/sm-mfa-plugin** with `tea repos create --login git.golem15.com --owner golem15 --name sm-mfa-plugin --private`. The API confirms `"private":true`. - - Remote `origin` = `git@git.golem15.com:golem15/sm-mfa-plugin.git`. - `git push -u origin master` pushed the new branch at `33ad164`, 6 commits. - Annotated tag **v0.1.0** on `33ad164` (tag object `b84dcbe`), pushed. 3. **sm-sociallogin-plugin:** @@ -233,28 +294,23 @@ Before every push I ran `git fetch` and checked that `origin/master..master` hel - Annotated tag **v0.1.4** on `b752177` (tag object `18af090`), pushed. 4. **vue-demo-app:** pushed master `21a22b6..44a5229`. That is the 4 named Phase 19.7 commits plus `44a5229`. No tag. 5. **sm-bm-app** (Task 6 part 2): pushed master `aafbcce..ebb2266`, this phase's 3 commits only. +6. **sm-demo-app** (`git@git.golem15.com:golem15/sm-demo-app.git`, Task 6 part 1): pushed master **`18597e5..bb24207`**, 23 commits. No tag. + - **Pre-push checks:** + - After `git fetch`, origin/master was still `18597e5` and `master..origin/master` was empty. + - `origin/master..master` was exactly the 19 authorised commits (`a25444e` … `40ed518`, all dated 2026-10-23) plus A-D (`0eb1f60`, `1c43e29`, `2e5b7da`, `bb24207`). + - Every gitlink those 23 commits introduce is on its submodule's origin: vue-demo-app `0125e29`, `21a22b6`, `3c53182`, `44a5229`, `9c247ab`, `b973a76`; user `3828a65`, `bfcfea4`, `3b22134`; journal `4ab94da`; oauthserver `116df7f`, `8bbec72`; sociallogin `b752177`; mfa `33ad164`. + - **After the push:** `origin/master..master` is empty and `ls-remote` shows `bb24207`. + +Read-only fetches also ran in the demo's user, sociallogin, mfa, journal and oauthserver submodules and in vue-demo-app. The acceptance checks pass: - `ls-remote --exit-code --tags` for v0.1.12, v0.1.0 and v0.1.4. - `grep -c 'sm-user-plugin v0.1.12' ../sm-mfa-plugin/go.mod` = 1. -- `origin/master..master` is empty for sm-user-plugin, vue-demo-app and sm-bm-app. - -## Open checkpoint: sm-demo-app (Task 6 part 1) - -`git -C ../sm-demo-app status --porcelain` shows: -- `M plugins/golem15/journal`, `M plugins/golem15/oauthserver`, `M plugins/golem15/user`: another session's uncommitted moves. - - Its user submodule clone is checked out at `50da92c` (v0.1.11). It made v0.1.11's last commit there on 2026-10-24. - - The committed gitlink is `bfcfea4` (v0.1.10), and go.mod requires v0.1.10. -- `M vue-demo-app`: this plan's `44a5229`. - -Commit A, the user bump, must move that same `plugins/golem15/user` pointer. Commits B and C cannot go first: sociallogin v0.1.4 and mfa v0.1.0 need v0.1.12's login gates, and the demo's go.work replaces the user module with that checkout. - -The plan says to stop when another session's edits touch a Task 6 file, and the Task 4 interpretation says to leave the user pointer move alone. So part (1) did not start, and nothing in sm-demo-app was changed. - -Proposed resolution: -- Move only the user checkout from v0.1.11 to v0.1.12. That is a superset, `50da92c` stays on origin, and the submodule's working tree is clean, so nothing is lost. -- Leave the journal and oauthserver moves unstaged. -- Then run commits A-D, the tests, and the push of the 19 prior commits plus A-D. +- `origin/master..master` is empty for sm-user-plugin, vue-demo-app, sm-bm-app and sm-demo-app. +- **sm-demo-app greps:** + - `grep -c 'id: golem15.mfa' summer.yaml` = 1 + - `grep -c 'git.golem15.com/golem15/sm-mfa-plugin v0.1.0' go.mod` = 1 + - `grep -c 'golem15.mfa' plugins.gen.go` = 1 ## Tests @@ -278,6 +334,15 @@ All Docker-backed tests ran against testcontainers Postgres (Docker reachable as - `pnpm test`: 202 tests pass, including `twoFactor.test.ts` (14). - `pnpm build`: ok. - Server render of `/account/security` and `/login`: 200. +- **sm-demo-app (Task 6 part 1):** + - **After commits A and B:** `go build ./...`, `go vet .` and `go test -short .` were green. + - **Before commit C:** + - Build and `go vet ./...` green. + - `-short ./...` green, untagged and with `-tags summercms_mcp`. + - Release-mode build green: `GOWORK=off go build -trimpath -tags summercms_mcp`, from the go.mod tags. + - `scripts/check-pins.sh`: user, sociallogin and mfa match their tags. It reports only the two leftover journal and oauthserver moves. + - **The plan's verify at HEAD `bb24207`:** `go build ./...`, `go vet .` and the three tests give exactly 3 `--- PASS: Test` lines (`TestBootAllPlugins`, `TestGoModRequiresTags`, `TestMFAMounted`). + - **Full suite (Docker) at `bb24207`:** `go test -count=1 ./...` is ok for every package, untagged and with `-tags summercms_mcp` (the MCP end-to-end tests). - **sm-bm-app:** - Build, vet and `-short` green after each of the 3 commits. The full suite is green too. - The plan's verify passes: `--- PASS: TestMFAMounted`. @@ -293,9 +358,9 @@ All Docker-backed tests ran against testcontainers Postgres (Docker reachable as - `go list -m all` has no go-webauthn. - The pointer moved in the bump commit. - **NOT RUN:** - - The demo verify (`TestMFAMounted`, `TestBootAllPlugins`, `TestGoModRequiresTags`): part (1) is open. + - `scripts/build.sh release` in sm-demo-app: it refuses the leftover journal and oauthserver moves (`require_clean`). Its Go step was run by hand as above. No Nuxt release build was made for the demo in this continuation. - A vue-demo-app type check: no tooling for it. - - A browser run of the demo screens. + - A browser run of the demo screens, and any deploy. ## Exported identifiers (for plan 04) @@ -349,6 +414,10 @@ All Docker-backed tests ran against testcontainers Postgres (Docker reachable as **sm-bm-app:** `TestMFAMounted` (`mfa_test.go`). +**sm-demo-app:** +- `TestMFAMounted` (`mfa_test.go`). +- `config/golem15.mfa.yaml`. + **vue-demo-app:** - **`app/lib/twoFactor.ts`:** - Functions `isTwoFactorChallenge`, `normalizeRecoveryCode`, `isTotpCode`, `challengeExpired`, `svgDataUrl`. @@ -384,8 +453,10 @@ See key-decisions in the frontmatter. - The push included Phase 19.7's `0125e29`, `b973a76`, `3c53182` and `9c247ab`. - The Task 4 reply authorised them by name. -**4. [Checkpoint] sm-demo-app part (1) not started** -- Another session's uncommitted `plugins/golem15/user` move touches a Task 6 file (see "Open checkpoint"). +**4. [Checkpoint, resolved] sm-demo-app part (1) waited on a second decision** +- The demo's user pointer had an uncommitted move to v0.1.11, left over from Phase 19.7. +- The user replied "proceed" (see "Task 6 sm-demo-app reply"). +- The user checkout was fast-forwarded to v0.1.12. The journal and oauthserver moves were left unstaged and are a pending todo. **5. [Rule 3, scope] fonoteka.go guard tests cover every user version the bump crosses** - **Problem:** the committed pointer was v0.1.10, but the guards had not followed it. `TestHiddenNeverMarshals` expected 8 models with 10 present. The parity migration count expected 11 with 14 present, and the account-link tables had no allowance. So the plan's "+1 for DeviceAuthSession" would have left them red. @@ -419,6 +490,31 @@ See key-decisions in the frontmatter. - Extra test coverage in `TestWebAuthnSmoke`, `TestPasswordlessSmoke` and `TestSocialGateSmoke`. - Demo UI extras: i18n keys and a cancel link. The commits and details are unchanged from the first draft (`2662252`, `6c8916f`, `44a5229`). +**16. [Rule 3, environment] The private sm-mfa-plugin repository and the demo's module-mode resolution** +- **Problem:** `go get`/`go mod tidy` with `GOWORK=off` could not fetch `git.golem15.com/golem15/sm-mfa-plugin@v0.1.0`: "could not read Username for 'https://git.golem15.com'". The repository is private; the other plugin repositories allow anonymous HTTPS. Commit C needs that fetch for the go.mod require and the go.sum hashes. +- **Fix:** for those commands only, the environment carried a git URL rewrite to SSH: + - `GIT_CONFIG_COUNT=1` + - `url.git@git.golem15.com:.insteadOf https://git.golem15.com/` + - `GOPRIVATE=git.golem15.com/*` + + No global or repository git config changed. +- **Consequence (open, deferred-items.md):** `scripts/build.sh release` and `scripts/check-pins.sh` fetch in module mode. On a machine without v0.1.0 in its module cache they fail until sm-mfa-plugin is public or the build host has credentials. The user decides. sm-bm-app is unaffected (it uses a replace). + +**17. [Precedent] Commit A also raises summercms v0.4.4 → v0.5.0** +- user v0.1.12 requires the framework at v0.5.0, so `go get` raised it. +- The subject names both, as `985af53` ("chore: bump user to v0.1.10 and require summercms v0.4.4") did; the plan's subject named only the user bump. + +**18. [Drift] Demo sociallogin moved from v0.1.2 to v0.1.4** +- The demo was on v0.1.2, not v0.1.3, so commit B also brings v0.1.3. Its message names v0.1.3's changes. + +**19. [Process] Commit B's message amended before the push** +- The first message understated v0.1.3 and named "the callback" instead of oauth-complete and oauth-register-complete. +- I amended my own unpushed commit (`9651dea` → `1c43e29`). Its tree is unchanged. + +**20. [Discretion] `config/golem15.mfa.yaml` does not offer webauthn** +- The plan set methods to `[totp, email]`, which already leaves webauthn out. The comment says why: the demo has no security-key screens. +- Passwordless sign-in stays at the plugin default, off. + ## Known Stubs None. @@ -430,31 +526,47 @@ None. None beyond the plan's register. - T-19.6-26..31 and T-19.6-33 are mitigated in code and tests. -- T-19.6-32: each push followed a fetch and a range check against the authorised commits. Nothing was force-pushed or deployed, and fonoteka.go was not pushed. +- T-19.6-32: each push followed a fetch, a range check against the authorised commits and, for sm-demo-app, a check that every introduced gitlink is on its origin. Nothing was force-pushed or deployed, and fonoteka.go was not pushed. -## Blockers +## Follow-ups -- **sm-demo-app user pointer** (another session's uncommitted move). The decision is needed before Task 6 part (1). +- **Pending todo** `.planning/todos/pending/2026-10-26-sm-demo-app-journal-oauthserver-pointers.md`: sm-demo-app's uncommitted journal (`4ab94da`→`b129902`) and oauthserver (`8bbec72`→`b6a9586`) moves, left over from Phase 19.7 plan 05. + - Both commits are on origin, but no tag sits on either one. + - v0.2.4 and v0.1.3 contain them, so the bump should go to those tags. +- **deferred-items.md** holds the private-repository build issue, plus the earlier items: + - sociallogin gofmt + - vue-demo-app type check + - five fonoteka Docker-backed failures + - fonoteka root go.mod require + - the mfa tag message +- **Plan 04 patch tags:** not authorised. Plan 04 must ask before any tag. ## Next -After the decision, the continuation agent: -- runs Task 6 part (1) in sm-demo-app: commits A-D, the demo verify, then the push of the 19 prior commits plus A-D; -- finalises this SUMMARY: requirements-completed and status complete; -- updates ROADMAP progress. +- Plan 04, the phase's unit tests. g15office: this executor has no g15office tool. The orchestrator posts the plan 03 update on `avoroeb4`. -## Self-Check: PASSED (draft) +## Self-Check: PASSED - **Commits exist:** - sm-mfa-plugin: `2662252`, `6c8916f`, `33ad164` - sm-sociallogin-plugin: `a8e3e78`, `b752177` - vue-demo-app: `44a5229` + - sm-demo-app: `0eb1f60`, `1c43e29`, `2e5b7da`, `bb24207` - sm-bm-app: `aad6004`, `376cff4`, `ebb2266` - fonoteka.go: `95fd58a` -- **Tags and branches are on origin:** v0.1.12, v0.1.0 and v0.1.4 via `ls-remote`, and sm-mfa-plugin master. + - summercms.go: `5a64611`, `4002bea` +- **Files exist:** + - `../sm-demo-app/mfa_test.go` + - `../sm-demo-app/config/golem15.mfa.yaml` + - `../sm-demo-app/plugins/golem15/mfa/go.mod` + - the pending todo +- **On origin:** + - Tags v0.1.12, v0.1.0 and v0.1.4. + - sm-mfa-plugin master. + - sm-demo-app master at `bb24207` (`ls-remote`). - **Working trees:** - - The working trees of sm-mfa-plugin, sm-sociallogin-plugin and fonoteka.go are clean. + - sm-demo-app keeps only the leftover ` M plugins/golem15/journal` and ` M plugins/golem15/oauthserver`. + - sm-mfa-plugin, sm-sociallogin-plugin and fonoteka.go are clean. - sm-bm-app keeps only the other session's planning edits and untracked paths. - - sm-demo-app is unchanged by this run. diff --git a/.planning/phases/19.6-two-factor-auth-and-device-flow-in-sm-user-plugin/deferred-items.md b/.planning/phases/19.6-two-factor-auth-and-device-flow-in-sm-user-plugin/deferred-items.md index 69464361..de4d395e 100644 --- a/.planning/phases/19.6-two-factor-auth-and-device-flow-in-sm-user-plugin/deferred-items.md +++ b/.planning/phases/19.6-two-factor-auth-and-device-flow-in-sm-user-plugin/deferred-items.md @@ -20,3 +20,9 @@ - sm-mfa-plugin: the v0.1.0 tag message says the two-factor mode is "optional, required or disabled" status: open **What:** the config values are `disabled`, `optional` and `enforced`. The tag is pushed and is not rewritten (that would need a force-push). The README and `config/config.yaml` are correct. The next release's tag message should name the right values. +- sm-demo-app: the release build needs read access to the private sm-mfa-plugin repository + status: open + **What:** found by 19.6-03 Task 6 part (1). `scripts/build.sh release` and `scripts/check-pins.sh` run with `GOWORK=off GOPRIVATE=git.golem15.com/*`, so Go fetches every required plugin over anonymous HTTPS. The other `sm-*-plugin` repositories allow that; sm-mfa-plugin is private, so the fetch fails ("could not read Username for 'https://git.golem15.com'"). On this machine the release build and the pins check pass, because v0.1.0 is already in the module cache: `go get` filled it through a one-command `url.git@git.golem15.com:.insteadOf https://git.golem15.com/` rewrite in the environment, and no global config was changed. A clean module cache, or another build machine, fails. The user decides: make sm-mfa-plugin public like the other plugins, or give the build host credentials (an `insteadOf` rewrite to SSH or a netrc) and document it in DEPLOY.md. sm-bm-app is not affected (it builds from the submodule through a replace). +- sm-demo-app: uncommitted journal and oauthserver submodule moves left over from Phase 19.7 plan 05 + status: open + **What:** tracked as the pending todo `.planning/todos/pending/2026-10-26-sm-demo-app-journal-oauthserver-pointers.md`. 19.6-03 left both unstaged. diff --git a/.planning/todos/pending/2026-10-26-sm-demo-app-journal-oauthserver-pointers.md b/.planning/todos/pending/2026-10-26-sm-demo-app-journal-oauthserver-pointers.md new file mode 100644 index 00000000..33bb6921 --- /dev/null +++ b/.planning/todos/pending/2026-10-26-sm-demo-app-journal-oauthserver-pointers.md @@ -0,0 +1,15 @@ +--- +title: Commit sm-demo-app's leftover journal and oauthserver submodule moves +date: 2026-10-26 +priority: medium +area: sm-demo-app +--- + +sm-demo-app: uncommitted journal (4ab94da→b129902) and oauthserver (8bbec72→b6a9586) submodule moves left over from Phase 19.7 plan 05 (2026-10-23); confirm the commits are on origin/tagged and commit the pointers (with go.mod bumps) as a 19.7 follow-up. + +Found by 19.6-03 Task 6, which left both unstaged and pushed sm-demo-app at `bb24207` with go.mod still on journal v0.2.3 and oauthserver v0.1.2. State on 2026-10-26: +- Both commits are on origin (journal `main`, oauthserver `master`) and both submodule trees are clean. +- No tag sits on either commit. Later tags contain them: journal v0.2.4 (`7fc07d8`) and oauthserver v0.1.3 (`df2eddd`). +- `TestGoModRequiresTags` and `scripts/check-pins.sh` need each submodule on the exact commit of the tag go.mod requires. So the bump moves each checkout to the tag, not to the current HEAD, and raises the go.mod requires (`GOWORK=off go get …@vX.Y.Z`, then `go mod tidy`). +- Make one `chore: bump to ` commit per plugin. +- Until then, `scripts/check-pins.sh` reports both mismatches and `scripts/build.sh release` refuses the dirty tree.