Keep private module fetches scoped and prove sticky status in browser
.amadan/ci.d/10-gate+1 −0Makefile+1 −1internal/slides/templates/editor.html+1 −1internal/slidestest/save_status_browser_test.go+3 −3
CI passed — run details
Intent
Independently review Slides SECOND adoption of Estilo shared save status, exact94ac454 in /home/paulca/amadan.net/oficina/slides/.claude/worktrees/overnight-save-status against deployed/editor-owner baseline a863fb6. Read-only; no mutations, deployments or additional agents. Read bounded diff /tmp/oficina-slides-status-review/branch.diff, relevant implementation/tests and actual committed bundle delivery. Do not audit unrelated history or whole app. Shared approved design: /home/paulca/amadan.net/oficina/estilo/.claude/worktrees/overnight-save-status/implementation/save-status.md. Library pinned real private module amadan.net/oficina/estilo.git@v0.0.0-20260907201639-532746acdbc1 (read savestatus package in Go module cache). Root owns library/Docs first adoption review independently. This branch includes CI support commit db7be72 cherry-picked from previously green998534c (separate review pending), adding npm tests, twice-regenerated committed bundle check and browser Go tests to existing full gate. No original editor branch or main changes authorized. Review both support and adoption changes but not baseline editor history. Adoption: shared Go template and CSS/JS bytes through rastrillo.Assets hashed same-origin URLs, import module URL from root.dataset before editor setup. Module load failure shows existing localized load error and throws, so editor never silently mounts without persistence feedback. Shared status uses existing Saved/Saving/Offline strings; offline maps retrying. App-owned adapter keeps dropped-batch sticky across resync/save success; load error has independent live region. Duplicate Slides status CSS/DOM-writing removed. No new product copy, CDN imports, local replace or public repo visibility. Evidence: rendered asset bytes/mime/hash/cache tests pass;103+ JS fixtures pass; real browser editing and permanent422 dropped-batch/resync/next-success test pass, sticky Offline, retrying remains at320px. Deliberately clearing dropped flag makes lifecycle test fail saved!=retrying. Full gate log /tmp/oficina-slides-status-review/gate.log currently running; do not claim complete until final gate:ok. Private pin fetched with GOPRIVATE=amadan.net and no committed replace. Original Slides owner retains main integration authority. Return concise APPROVE or CHANGES REQUIRED, concrete blocking findings, and any remaining canary/review preconditions. Verify module failure flow in bundle, sticky-save/load-error independence, shared asset routing/security, semantic accessibility, and CI hidden-success paths. Avoid suggestions that change existing user strings.
diff --git a/.amadan/ci.d/10-gate b/.amadan/ci.d/10-gate| index 9dc4388..ad3a390 100755 |
| --- a/.amadan/ci.d/10-gate |
| +++ b/.amadan/ci.d/10-gate |
| @@ -3,6 +3,7 @@ |
| # squash-merge, in one script, so what the runner executes and what you |
| # run before pushing are one definition rather than two that drift. |
| set -euo pipefail |
| +export GOPRIVATE="${GOPRIVATE:+$GOPRIVATE,}amadan.net/oficina/estilo.git" |
| # Run from the repo root whatever the caller's working directory is: |
| # .amadan/ci execs this file, an amadan runner with step support runs it |
diff --git a/Makefile b/Makefile| index fb19311..e6e8101 100644 |
| --- a/Makefile |
| +++ b/Makefile |
| @@ -42,7 +42,7 @@ build: |
| # that. rastrillo dev never strips, for the same reason. |
| release: version-check |
| @mkdir -p releases |
| - CGO_ENABLED=0 GOOS=$(RELEASE_GOOS) GOARCH=$(RELEASE_GOARCH) \ |
| + GOPRIVATE="$${GOPRIVATE:+$$GOPRIVATE,}amadan.net/oficina/estilo.git" CGO_ENABLED=0 GOOS=$(RELEASE_GOOS) GOARCH=$(RELEASE_GOARCH) \ |
| go build -ldflags="-s -w -X 'amadan.net/rastrillo/rastrillo.BuildVersion=$(VERSION)'" \ |
| -o $(RELEASE_BIN) ./cmd/$(APP) |
| @echo |
diff --git a/internal/slides/templates/editor.html b/internal/slides/templates/editor.html| index 4ce7f63..68be6c8 100644 |
| --- a/internal/slides/templates/editor.html |
| +++ b/internal/slides/templates/editor.html |
| @@ -79,7 +79,7 @@ |
| <button rst-btn="primary" type="submit">{{.PresentLabel}}</button> |
| </form> |
| {{template "estilo-save-status" .SaveStatus}} |
| - <span slides-load-error role="status" aria-live="polite"></span> |
| + <span slides-load-error role="status" aria-live="polite" aria-atomic="true"></span> |
| </header> |
| {{/* One strip item, the shape the bundle clones for a slide it adds: |
diff --git a/internal/slidestest/save_status_browser_test.go b/internal/slidestest/save_status_browser_test.go| index 4c99183..750f6e5 100644 |
| --- a/internal/slidestest/save_status_browser_test.go |
| +++ b/internal/slidestest/save_status_browser_test.go |
| @@ -23,9 +23,9 @@ func TestBrowserDroppedBatchStatusStaysOfflineAfterRecovery(t *testing.T) { |
| let rejectNext = true; |
| window.fetch = async (...args) => { |
| if (String(args[0]).endsWith('/updates') && args[1]?.method === 'POST') { |
| - if (rejectNext) { rejectNext = false; return new Response('', {status:422}); } |
| + if (rejectNext) { rejectNext = false; setTimeout(() => window.statusProbeRejected = true, 0); return new Response('', {status:422}); } |
| const response = await fetchBefore(...args); |
| - if (response.ok) window.statusProbeSaved = true; |
| + if (response.ok) setTimeout(() => window.statusProbeSaved = true, 0); |
| return response; |
| } |
| return fetchBefore(...args); |
| @@ -33,7 +33,7 @@ func TestBrowserDroppedBatchStatusStaysOfflineAfterRecovery(t *testing.T) { |
| })()`, nil), |
| chromedp.Click(heading, chromedp.ByQuery), |
| chromedp.SendKeys(heading, string(kb.End)+" discarded-fixture", chromedp.ByQuery), |
| - waitFor(`document.querySelector('[estilo-save-status]').dataset.state === 'retrying'`), |
| + waitFor(`window.statusProbeRejected === true`), |
| waitFor(`!document.querySelector('`+heading+`').textContent.includes('discarded-fixture')`), |
| chromedp.Click(heading, chromedp.ByQuery), |
| chromedp.SendKeys(heading, string(kb.End)+" retained-fixture", chromedp.ByQuery), |