oficina / docs Public

Move Docs off rastrillo's frozen pre-move path

Docs took rastrillo's ui, auth, sessions, db, migrate, mail and csrf from
github.com/carlosframework/rastrillo, frozen at v0.23.0, and only
assertion, crypto and one sessions reader from amadan.net/rastrillo. Every
import is now amadan.net/rastrillo/rastrillo, at the d9c28d7 Docs already
required (v0.26.1-0.20260908132728), so the build has one rastrillo
rather than two. It is a descendant of 29e4491 (Sheets' pin) by three
commits, all in sessions (FromContext, the context-bounded lookup the
team session reader already used).

- The CLI is pinned as a go.mod tool at the same version.
- build-release.sh stamps amadan.net/rastrillo/rastrillo.BuildVersion; the
  old symbol would leave /api/version answering "dev".
- team_session_reader.go no longer converts between two Session types.
- One pre-move import remains, aliased presessions in native.go, because
  rastrillo/native's server still takes the old *sessions.Sessions. Both
  packages share the sessions table. TestNoPreMoveRastrillo forbids any
  other, and TestNoSessionsUserID now bans UserID on both paths.
- go tool rastrillo doctor --fix finds nothing vendored on disk (Docs
  serves every asset from memory) and writes nothing.
  TestBusyRuleIsLinkedAndServed now fails if a rastrillo.js, busy.js,
  tokens.css or picker script ever lands in static/ or brand/.
- The principal-compat probe files open the db through the step file, so
  the shared main compiles against both trees.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev 5c168c6d068dd3027aaebceb3d86fb92af07fa64 parent fbd51b1
58 files changed, +235 −93
  • AGENTS.md +22 −0
  • cmd/docs/main.go +2 −2
  • go.mod +3 −0
  • go.sum +2 −0
  • internal/docs/app.go +6 −6
  • internal/docs/auth.go +4 −4
  • internal/docs/auth_navigation.go +1 −1
  • internal/docs/chrome.go +2 −2
  • internal/docs/content_maintenance.go +2 −2
  • internal/docs/content_maintenance_test.go +1 −1
  • internal/docs/content_recovery_test.go +1 −1
  • internal/docs/content_scrub.go +1 −1
  • internal/docs/errors.go +1 −1
  • internal/docs/export.go +1 −1
  • internal/docs/handlers.go +1 −1
  • internal/docs/home_exchange.go +2 −2
  • internal/docs/home_exchange_test.go +4 −4
  • internal/docs/home_local_navigation.go +2 −2
  • internal/docs/home_local_navigation_test.go +2 −2
  • internal/docs/home_render.go +1 −1
  • internal/docs/home_router_integration_test.go +1 −1
  • internal/docs/home_routes.go +4 −4
  • internal/docs/home_security_test.go +1 −1
  • internal/docs/identity.go +2 −2
  • internal/docs/identity_test.go +1 −1
  • internal/docs/linkstore/store.go +1 −1
  • internal/docs/menu.go +1 −1
  • internal/docs/models.go +1 −1
  • internal/docs/native.go +20 −1
  • internal/docs/principalstore/store.go +1 −1
  • internal/docs/principalstore/store_test.go +2 −2
  • internal/docs/principalstore/testdata/compat_main.go.txt +1 −2
  • internal/docs/principalstore/testdata/compat_new.go.txt +6 −2
  • internal/docs/principalstore/testdata/compat_old.go.txt +4 −0
  • internal/docs/publish.go +1 −1
  • internal/docs/render.go +2 −2
  • internal/docs/search.go +1 −1
  • internal/docs/share.go +1 −1
  • internal/docs/signin_door_test.go +1 −1
  • internal/docs/signin_return.go +1 −1
  • internal/docs/stream.go +1 −1
  • internal/docs/team_access.go +1 −1
  • internal/docs/team_access_test.go +2 −2
  • internal/docs/team_config.go +2 −2
  • internal/docs/team_emission.go +1 −1
  • internal/docs/team_home.go +1 −1
  • internal/docs/team_home_test.go +1 −1
  • internal/docs/team_identity_test.go +1 −1
  • internal/docs/team_router_test.go +1 −1
  • internal/docs/team_session_reader.go +6 −7
  • internal/docs/team_session_reader_test.go +1 −1
  • internal/docs/team_stream.go +1 −1
  • internal/docs/teamstate/store.go +1 −1
  • internal/docs/teamstate/store_test.go +2 −2
  • internal/docs/theme_assets_test.go +18 −1
  • internal/lint/no_premove_rastrillo_test.go +69 −0
  • internal/lint/no_sessions_userid_test.go +11 −7
  • scripts/build-release.sh +1 −1
diff --git a/AGENTS.md b/AGENTS.md
index 6670b36..bb74ee4 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -410,6 +410,28 @@ who mentioned it first. (Written after exactly that: a merge commit on
on to Paul as one, when `amadan branch merge` produces a merge commit
itself and the branch had landed correctly. One minute with the tool
would have caught it.)
+- **rastrillo is `amadan.net/rastrillo/rastrillo`.** The old path,
+ `github.com/carlosframework/rastrillo`, stops at v0.23.0: code importing
+ it gets no fix, and its own checks cannot tell (Docs zoomed iOS on every
+ tap for a month that way). `TestNoPreMoveRastrillo` (internal/lint)
+ allows one import of it, native.go's bridge to rastrillo/native's
+ server, until that server moves. The CLI is pinned as a `tool` in
+ go.mod: run it as `go tool rastrillo …`, never a `rastrillo` from PATH.
+ `scripts/build-release.sh` stamps `amadan.net/rastrillo/rastrillo.BuildVersion`;
+ the old symbol leaves `/api/version` answering "dev"
+ (`TestReleaseBinaryReportsItsVersion`).
+- **Docs serves rastrillo's and estilo's assets from memory**
+ (render.go's `vendoredStaticFS`), so `go tool rastrillo doctor` finds
+ nothing vendored to check. If a future `doctor --fix` ever writes a
+ rastrillo.js, busy.js or tokens.css to disk, delete it: doctor's shim
+ carries the old busy rule, which fights estilo's busy.js.
+ `TestBusyRuleIsLinkedAndServed` fails if one is left behind.
+- **iOS zooms into any text control under 16px.** tokens.css lifts
+ controls to 16px under `(pointer: coarse)`; a Docs rule that sets a
+ control's font with a heavier selector must restate
+ `font-size: max(1rem, 1em)` there too. `TestNoZoomOnTap` (browser tag:
+ `go test -tags browser -run OnTap ./internal/docs/`, needs a Chromium via
+ `RASTRILLO_CHROME` or a Playwright cache) measures every field.
- **Re-copy `tokens.css` deliberately on every rastrillo upgrade.** It is
frozen into `static/` at scaffold time while the partials upgrade with the
module. `rastrillo doctor` will make this mechanical; until it lands it is
diff --git a/cmd/docs/main.go b/cmd/docs/main.go
index f040af6..0fdd9d5 100644
--- a/cmd/docs/main.go
+++ b/cmd/docs/main.go
@@ -8,8 +8,8 @@ import (
"os"
"strings"
- "github.com/carlosframework/rastrillo"
- "github.com/carlosframework/rastrillo/mail"
+ "amadan.net/rastrillo/rastrillo"
+ "amadan.net/rastrillo/rastrillo/mail"
"github.com/carlosframework/docs/internal/docs"
)
diff --git a/go.mod b/go.mod
index 93b5520..4009037 100644
--- a/go.mod
+++ b/go.mod
@@ -22,6 +22,7 @@ require (
)
require (
+ github.com/BurntSushi/toml v1.6.0 // indirect
github.com/chromedp/sysutil v1.1.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
@@ -38,3 +39,5 @@ require (
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
)
+
+tool amadan.net/rastrillo/rastrillo/cmd/rastrillo
diff --git a/go.sum b/go.sum
index e791c77..c647bc4 100644
--- a/go.sum
+++ b/go.sum
@@ -8,6 +8,8 @@ amadan.net/rastrillo/native/server v0.0.0-20260923173546-2a5d07b2c8d3 h1:5EFx7BL
amadan.net/rastrillo/native/server v0.0.0-20260923173546-2a5d07b2c8d3/go.mod h1:ZaaxeE278dJltdrLwmwpxUjQ5wuKzqDAVSNRet+WupY=
amadan.net/rastrillo/rastrillo v0.26.1-0.20260908132728-d9c28d708556 h1:/vHMeq9T+PZmUACixGkg32YEjyM8s31+bfAqqrMha0A=
amadan.net/rastrillo/rastrillo v0.26.1-0.20260908132728-d9c28d708556/go.mod h1:RpyHVPD0udcSfHJroY0KZE/FUjgw6Tvfo8SJm2qeZGE=
+github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
+github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/carlosframework/rastrillo v0.23.0 h1:tKAAlwPt4Pg/rkqk7o6jvV12bbZ0r34oEVpuOlKfX7w=
github.com/carlosframework/rastrillo v0.23.0/go.mod h1:pZlrE5F5OhspvZFzef0DrfjHAjA8FXycb9J5/8vc8Tw=
github.com/chromedp/cdproto v0.0.0-20250724212937-08a3db8b4327 h1:UQ4AU+BGti3Sy/aLU8KVseYKNALcX9UXY6DfpwQ6J8E=
diff --git a/internal/docs/app.go b/internal/docs/app.go
index 9e325c8..c834041 100644
--- a/internal/docs/app.go
+++ b/internal/docs/app.go
@@ -26,12 +26,12 @@ import (
"amadan.net/oficina/estilo.git/theme"
"amadan.net/oficina/home/handoff"
nativeauth "amadan.net/rastrillo/native/server"
+ "amadan.net/rastrillo/rastrillo"
+ "amadan.net/rastrillo/rastrillo/db"
+ "amadan.net/rastrillo/rastrillo/mail"
+ "amadan.net/rastrillo/rastrillo/migrate"
+ "amadan.net/rastrillo/rastrillo/sessions"
"github.com/carlosframework/docs/internal/docs/linkstore"
- "github.com/carlosframework/rastrillo"
- "github.com/carlosframework/rastrillo/db"
- "github.com/carlosframework/rastrillo/mail"
- "github.com/carlosframework/rastrillo/migrate"
- "github.com/carlosframework/rastrillo/sessions"
"github.com/go-chi/chi/v5"
"github.com/carlosframework/docs/internal/core"
@@ -539,7 +539,7 @@ func New(cfg Config) (*App, error) {
current.ServeHTTP(w, sessions.WithSession(r, session))
})
}
- nativeSessions, err := sessions.New(sessions.Config{DB: d.Writer(), Origin: cfg.Origin, SigninPath: "/signin", Logger: logger})
+ nativeSessions, err := newNativeSessions(d.Writer(), cfg.Origin, logger)
if err != nil {
rt.Close(context.Background())
d.Close()
diff --git a/internal/docs/auth.go b/internal/docs/auth.go
index 9fb5014..fa24870 100644
--- a/internal/docs/auth.go
+++ b/internal/docs/auth.go
@@ -16,11 +16,11 @@ import (
"amadan.net/oficina/estilo.git/brand"
"amadan.net/oficina/estilo.git/chrome"
"amadan.net/oficina/estilo.git/sky"
- rauth "github.com/carlosframework/rastrillo/auth"
- "github.com/carlosframework/rastrillo/mail"
- "github.com/carlosframework/rastrillo/sessions"
+ rauth "amadan.net/rastrillo/rastrillo/auth"
+ "amadan.net/rastrillo/rastrillo/mail"
+ "amadan.net/rastrillo/rastrillo/sessions"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
)
// authSchema aliases rauth.Schema — auth's own migrations, merged into
diff --git a/internal/docs/auth_navigation.go b/internal/docs/auth_navigation.go
index 89caf7b..b2e828a 100644
--- a/internal/docs/auth_navigation.go
+++ b/internal/docs/auth_navigation.go
@@ -9,7 +9,7 @@ import (
"net/url"
"strings"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
)
// End the POST with a document before navigating to an identity provider.
diff --git a/internal/docs/chrome.go b/internal/docs/chrome.go
index 8617f6e..ffa37db 100644
--- a/internal/docs/chrome.go
+++ b/internal/docs/chrome.go
@@ -17,8 +17,8 @@ import (
"amadan.net/oficina/estilo.git/brand"
"amadan.net/oficina/estilo.git/chrome"
estilomenu "amadan.net/oficina/estilo.git/menu"
- "github.com/carlosframework/rastrillo"
- "github.com/carlosframework/rastrillo/sessions"
+ "amadan.net/rastrillo/rastrillo"
+ "amadan.net/rastrillo/rastrillo/sessions"
)
// Frame is what views/layout.html reads from every page: the bar, the
diff --git a/internal/docs/content_maintenance.go b/internal/docs/content_maintenance.go
index af3f84d..0b9a739 100644
--- a/internal/docs/content_maintenance.go
+++ b/internal/docs/content_maintenance.go
@@ -6,8 +6,8 @@ import (
"log/slog"
"os"
- "github.com/carlosframework/rastrillo/db"
- "github.com/carlosframework/rastrillo/migrate"
+ "amadan.net/rastrillo/rastrillo/db"
+ "amadan.net/rastrillo/rastrillo/migrate"
)
type ContentMaintenanceConfig struct {
diff --git a/internal/docs/content_maintenance_test.go b/internal/docs/content_maintenance_test.go
index bf52cac..ee54f15 100644
--- a/internal/docs/content_maintenance_test.go
+++ b/internal/docs/content_maintenance_test.go
@@ -9,7 +9,7 @@ import (
"path/filepath"
"testing"
- "github.com/carlosframework/rastrillo/db"
+ "amadan.net/rastrillo/rastrillo/db"
)
func TestContentMaintenanceRequiresExpectedKeyBeforeOpeningDatabase(t *testing.T) {
diff --git a/internal/docs/content_recovery_test.go b/internal/docs/content_recovery_test.go
index b87e3f3..7ce68f9 100644
--- a/internal/docs/content_recovery_test.go
+++ b/internal/docs/content_recovery_test.go
@@ -12,7 +12,7 @@ import (
"testing"
"time"
- "github.com/carlosframework/rastrillo/db"
+ "amadan.net/rastrillo/rastrillo/db"
"gorm.io/gorm"
)
diff --git a/internal/docs/content_scrub.go b/internal/docs/content_scrub.go
index be113f7..81e4d16 100644
--- a/internal/docs/content_scrub.go
+++ b/internal/docs/content_scrub.go
@@ -5,7 +5,7 @@ import (
"database/sql"
"fmt"
- "github.com/carlosframework/rastrillo/db"
+ "amadan.net/rastrillo/rastrillo/db"
)
func scrubContent(ctx context.Context, d *db.DB, c *contentCipher) error {
diff --git a/internal/docs/errors.go b/internal/docs/errors.go
index 83eda15..68c9dbf 100644
--- a/internal/docs/errors.go
+++ b/internal/docs/errors.go
@@ -25,7 +25,7 @@ import (
"strings"
"amadan.net/oficina/estilo.git/chrome"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
"github.com/go-chi/chi/v5"
)
diff --git a/internal/docs/export.go b/internal/docs/export.go
index ed8a4a6..4853622 100644
--- a/internal/docs/export.go
+++ b/internal/docs/export.go
@@ -16,7 +16,7 @@ import (
"strings"
"unicode"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
"github.com/carlosframework/docs/internal/export"
"github.com/carlosframework/docs/internal/fonts"
diff --git a/internal/docs/handlers.go b/internal/docs/handlers.go
index 8be994f..8a703d2 100644
--- a/internal/docs/handlers.go
+++ b/internal/docs/handlers.go
@@ -17,7 +17,7 @@ import (
"amadan.net/oficina/estilo.git/chrome"
estilomenu "amadan.net/oficina/estilo.git/menu"
"amadan.net/oficina/estilo.git/savestatus"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
"github.com/carlosframework/docs/internal/core"
)
diff --git a/internal/docs/home_exchange.go b/internal/docs/home_exchange.go
index ec0b796..a420fad 100644
--- a/internal/docs/home_exchange.go
+++ b/internal/docs/home_exchange.go
@@ -12,9 +12,9 @@ import (
"amadan.net/oficina/home/handoff"
"amadan.net/oficina/home/handoff/seal"
"amadan.net/rastrillo/rastrillo/assertion"
+ rauth "amadan.net/rastrillo/rastrillo/auth"
+ "amadan.net/rastrillo/rastrillo/sessions"
"github.com/carlosframework/docs/internal/docs/linkstore"
- rauth "github.com/carlosframework/rastrillo/auth"
- "github.com/carlosframework/rastrillo/sessions"
"gorm.io/gorm"
)
diff --git a/internal/docs/home_exchange_test.go b/internal/docs/home_exchange_test.go
index 49ad50b..68ff9ca 100644
--- a/internal/docs/home_exchange_test.go
+++ b/internal/docs/home_exchange_test.go
@@ -12,12 +12,12 @@ import (
"amadan.net/oficina/home/handoff"
"amadan.net/rastrillo/rastrillo/assertion"
+ rauth "amadan.net/rastrillo/rastrillo/auth"
assertioncrypto "amadan.net/rastrillo/rastrillo/crypto"
+ "amadan.net/rastrillo/rastrillo/csrf"
+ "amadan.net/rastrillo/rastrillo/migrate"
+ "amadan.net/rastrillo/rastrillo/sessions"
"github.com/carlosframework/docs/internal/docs/linkstore"
- rauth "github.com/carlosframework/rastrillo/auth"
- "github.com/carlosframework/rastrillo/csrf"
- "github.com/carlosframework/rastrillo/migrate"
- "github.com/carlosframework/rastrillo/sessions"
)
const bridgeOrigin = "https://blue.docs.oficina.works"
diff --git a/internal/docs/home_local_navigation.go b/internal/docs/home_local_navigation.go
index e5886d2..4dde2d0 100644
--- a/internal/docs/home_local_navigation.go
+++ b/internal/docs/home_local_navigation.go
@@ -10,8 +10,8 @@ import (
"time"
"amadan.net/oficina/home/handoff"
- "github.com/carlosframework/rastrillo"
- "github.com/carlosframework/rastrillo/sessions"
+ "amadan.net/rastrillo/rastrillo"
+ "amadan.net/rastrillo/rastrillo/sessions"
)
const localLinkNavigationCookie = "__Host-oficina-docs-local-link-navigation"
diff --git a/internal/docs/home_local_navigation_test.go b/internal/docs/home_local_navigation_test.go
index 5b2c3e1..5299f88 100644
--- a/internal/docs/home_local_navigation_test.go
+++ b/internal/docs/home_local_navigation_test.go
@@ -13,8 +13,8 @@ import (
"time"
"amadan.net/oficina/home/handoff/seal"
- rauth "github.com/carlosframework/rastrillo/auth"
- "github.com/carlosframework/rastrillo/sessions"
+ rauth "amadan.net/rastrillo/rastrillo/auth"
+ "amadan.net/rastrillo/rastrillo/sessions"
)
const navigationOrigin = "https://docs.example.com"
diff --git a/internal/docs/home_render.go b/internal/docs/home_render.go
index 5911302..8499631 100644
--- a/internal/docs/home_render.go
+++ b/internal/docs/home_render.go
@@ -6,7 +6,7 @@ import (
"amadan.net/oficina/estilo.git/brand"
"amadan.net/oficina/estilo.git/chrome"
"amadan.net/oficina/estilo.git/sky"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
)
// homeLinkPage is views/home_link.html's data: the Home account-connection
diff --git a/internal/docs/home_router_integration_test.go b/internal/docs/home_router_integration_test.go
index 6f83458..399903a 100644
--- a/internal/docs/home_router_integration_test.go
+++ b/internal/docs/home_router_integration_test.go
@@ -16,7 +16,7 @@ import (
"amadan.net/rastrillo/rastrillo/assertion"
assertioncrypto "amadan.net/rastrillo/rastrillo/crypto"
- "github.com/carlosframework/rastrillo/sessions"
+ "amadan.net/rastrillo/rastrillo/sessions"
)
type routerHomeFixture struct {
diff --git a/internal/docs/home_routes.go b/internal/docs/home_routes.go
index 496c626..92f8686 100644
--- a/internal/docs/home_routes.go
+++ b/internal/docs/home_routes.go
@@ -9,10 +9,10 @@ import (
"amadan.net/oficina/home/handoff"
"amadan.net/oficina/home/handoff/seal"
- "github.com/carlosframework/rastrillo"
- rauth "github.com/carlosframework/rastrillo/auth"
- "github.com/carlosframework/rastrillo/csrf"
- "github.com/carlosframework/rastrillo/sessions"
+ "amadan.net/rastrillo/rastrillo"
+ rauth "amadan.net/rastrillo/rastrillo/auth"
+ "amadan.net/rastrillo/rastrillo/csrf"
+ "amadan.net/rastrillo/rastrillo/sessions"
"github.com/go-chi/chi/v5"
)
diff --git a/internal/docs/home_security_test.go b/internal/docs/home_security_test.go
index 7644f1b..8bc59c2 100644
--- a/internal/docs/home_security_test.go
+++ b/internal/docs/home_security_test.go
@@ -6,7 +6,7 @@ import (
"strings"
"testing"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
)
func TestHomeFormPolicyPreservesFrameworkAndStandalone(t *testing.T) {
diff --git a/internal/docs/identity.go b/internal/docs/identity.go
index f070227..95a5a9c 100644
--- a/internal/docs/identity.go
+++ b/internal/docs/identity.go
@@ -8,8 +8,8 @@ import (
"net/http"
"time"
- "github.com/carlosframework/rastrillo"
- "github.com/carlosframework/rastrillo/sessions"
+ "amadan.net/rastrillo/rastrillo"
+ "amadan.net/rastrillo/rastrillo/sessions"
"gorm.io/gorm"
)
diff --git a/internal/docs/identity_test.go b/internal/docs/identity_test.go
index dc0fd88..48d5447 100644
--- a/internal/docs/identity_test.go
+++ b/internal/docs/identity_test.go
@@ -8,7 +8,7 @@ import (
"testing"
"time"
- "github.com/carlosframework/rastrillo/sessions"
+ "amadan.net/rastrillo/rastrillo/sessions"
)
func identityRequest(method, subject, authMethod string) *http.Request {
diff --git a/internal/docs/linkstore/store.go b/internal/docs/linkstore/store.go
index d0e5f50..3797989 100644
--- a/internal/docs/linkstore/store.go
+++ b/internal/docs/linkstore/store.go
@@ -18,7 +18,7 @@ import (
"amadan.net/oficina/home/handoff"
"amadan.net/oficina/home/handoff/seal"
- "github.com/carlosframework/rastrillo/migrate"
+ "amadan.net/rastrillo/rastrillo/migrate"
)
//go:embed migrations/*.sql
diff --git a/internal/docs/menu.go b/internal/docs/menu.go
index f561a96..a09f0b9 100644
--- a/internal/docs/menu.go
+++ b/internal/docs/menu.go
@@ -51,7 +51,7 @@ import (
"net/http"
estilomenu "amadan.net/oficina/estilo.git/menu"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
)
// Menu item kinds. The kind decides what show.html renders, and each
diff --git a/internal/docs/models.go b/internal/docs/models.go
index bfc6c6f..0522305 100644
--- a/internal/docs/models.go
+++ b/internal/docs/models.go
@@ -4,7 +4,7 @@ import (
"embed"
"time"
- "github.com/carlosframework/rastrillo/migrate"
+ "amadan.net/rastrillo/rastrillo/migrate"
)
// migrationFS embeds this app's own numbered migrations — per
diff --git a/internal/docs/native.go b/internal/docs/native.go
index 025d9a0..93197de 100644
--- a/internal/docs/native.go
+++ b/internal/docs/native.go
@@ -1,13 +1,32 @@
package docs
import (
+ "database/sql"
"encoding/json"
- "github.com/carlosframework/rastrillo"
+ "log/slog"
"net/http"
"strings"
"time"
+
+ "amadan.net/rastrillo/rastrillo"
+
+ // The one import left on rastrillo's pre-move path, on purpose:
+ // rastrillo/native's server (2a5d07b, and its main) still takes a
+ // github.com/carlosframework/rastrillo *sessions.Sessions. Both
+ // sessions packages read and write the same sessions table, so a
+ // session native sign-in mints is an ordinary session to the app
+ // (native_exchange_test.go). Move this to
+ // amadan.net/rastrillo/rastrillo/sessions when native/server moves;
+ // TestNoPreMoveRastrillo forbids every other import of the old path.
+ presessions "github.com/carlosframework/rastrillo/sessions"
)
+// newNativeSessions is the sessions handle rastrillo/native's server
+// approves and mints with, over the app's own database.
+func newNativeSessions(db *sql.DB, origin string, logger *slog.Logger) (*presessions.Sessions, error) {
+ return presessions.New(presessions.Config{DB: db, Origin: origin, SigninPath: "/signin", Logger: logger})
+}
+
func wantsNative(r *http.Request) bool {
return strings.Contains(r.Header.Get("Accept"), "application/json")
}
diff --git a/internal/docs/principalstore/store.go b/internal/docs/principalstore/store.go
index e3409cb..b913833 100644
--- a/internal/docs/principalstore/store.go
+++ b/internal/docs/principalstore/store.go
@@ -12,7 +12,7 @@ import (
"time"
"unicode/utf8"
- "github.com/carlosframework/rastrillo/migrate"
+ "amadan.net/rastrillo/rastrillo/migrate"
)
//go:embed migrations/*.sql
diff --git a/internal/docs/principalstore/store_test.go b/internal/docs/principalstore/store_test.go
index c443785..c3786b4 100644
--- a/internal/docs/principalstore/store_test.go
+++ b/internal/docs/principalstore/store_test.go
@@ -8,11 +8,11 @@ import (
"sync"
"testing"
+ "amadan.net/rastrillo/rastrillo/db"
+ "amadan.net/rastrillo/rastrillo/migrate"
"github.com/carlosframework/docs/internal/docs"
"github.com/carlosframework/docs/internal/docs/linkstore"
p "github.com/carlosframework/docs/internal/docs/principalstore"
- "github.com/carlosframework/rastrillo/db"
- "github.com/carlosframework/rastrillo/migrate"
)
const issuer = "https://id.oficina.works"
diff --git a/internal/docs/principalstore/testdata/compat_main.go.txt b/internal/docs/principalstore/testdata/compat_main.go.txt
index 63c67e7..bc0ace2 100644
--- a/internal/docs/principalstore/testdata/compat_main.go.txt
+++ b/internal/docs/principalstore/testdata/compat_main.go.txt
@@ -9,7 +9,6 @@ import (
"fmt"
"github.com/carlosframework/docs/internal/core"
"github.com/carlosframework/docs/internal/docs"
- "github.com/carlosframework/rastrillo/db"
"io"
"log/slog"
"os"
@@ -29,7 +28,7 @@ func main() {
app, e := docs.New(docs.Config{DBPath: *path, Env: "development", Origin: "https://compat.example", SampleDocuments: "false", Logger: slog.New(slog.NewTextHandler(io.Discard, nil))})
must(e)
defer app.Close()
- d, e := db.Open(*path, nil)
+ d, e := openProbeDB(*path)
must(e)
defer d.Close()
id, e := app.Store().EnsurePerson(ctx, *address)
diff --git a/internal/docs/principalstore/testdata/compat_new.go.txt b/internal/docs/principalstore/testdata/compat_new.go.txt
index b55d4a8..2bbbcfd 100644
--- a/internal/docs/principalstore/testdata/compat_new.go.txt
+++ b/internal/docs/principalstore/testdata/compat_new.go.txt
@@ -5,10 +5,14 @@ import (
"github.com/carlosframework/docs/internal/docs"
"github.com/carlosframework/docs/internal/docs/linkstore"
p "github.com/carlosframework/docs/internal/docs/principalstore"
- "github.com/carlosframework/rastrillo/db"
- "github.com/carlosframework/rastrillo/migrate"
+ "amadan.net/rastrillo/rastrillo/db"
+ "amadan.net/rastrillo/rastrillo/migrate"
)
+// openProbeDB lives in the step file because the old and new trees import
+// rastrillo's db from different module paths.
+func openProbeDB(path string) (*db.DB, error) { return db.Open(path, nil) }
+
func principalStep(ctx context.Context, d *db.DB, phase string) int64 {
_, e := migrate.Apply(ctx, d, migrate.Merge(linkstore.Schema, p.Schema))
must(e)
diff --git a/internal/docs/principalstore/testdata/compat_old.go.txt b/internal/docs/principalstore/testdata/compat_old.go.txt
index a0143f4..ffb28d5 100644
--- a/internal/docs/principalstore/testdata/compat_old.go.txt
+++ b/internal/docs/principalstore/testdata/compat_old.go.txt
@@ -8,6 +8,10 @@ import (
func principalStep(context.Context, *db.DB, string) int64 { return 0 }
+// openProbeDB lives in the step file because the old and new trees import
+// rastrillo's db from different module paths.
+func openProbeDB(path string) (*db.DB, error) { return db.Open(path, nil) }
+
func fixtureActor(id int64, address string) docs.Actor {
return docs.Actor{PersonID: id, Subject: address}
}
diff --git a/internal/docs/publish.go b/internal/docs/publish.go
index 7d6fb1f..af0f792 100644
--- a/internal/docs/publish.go
+++ b/internal/docs/publish.go
@@ -5,7 +5,7 @@ import (
"html/template"
"net/http"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
"gorm.io/gorm"
)
diff --git a/internal/docs/render.go b/internal/docs/render.go
index ef7d4c6..fd82cfe 100644
--- a/internal/docs/render.go
+++ b/internal/docs/render.go
@@ -16,8 +16,8 @@ import (
estilomenu "amadan.net/oficina/estilo.git/menu"
"amadan.net/oficina/estilo.git/savestatus"
"amadan.net/oficina/estilo.git/theme"
- "github.com/carlosframework/rastrillo"
- "github.com/carlosframework/rastrillo/ui"
+ "amadan.net/rastrillo/rastrillo"
+ "amadan.net/rastrillo/rastrillo/ui"
)
// There is no rastrillo shell any more. The topbar shell's bar hard-coded
diff --git a/internal/docs/search.go b/internal/docs/search.go
index f0203ac..a946af8 100644
--- a/internal/docs/search.go
+++ b/internal/docs/search.go
@@ -14,7 +14,7 @@ import (
"time"
"unicode"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
"golang.org/x/text/unicode/norm"
)
diff --git a/internal/docs/share.go b/internal/docs/share.go
index 76cc7d5..70201a2 100644
--- a/internal/docs/share.go
+++ b/internal/docs/share.go
@@ -4,7 +4,7 @@ import (
"errors"
"net/http"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
)
// sharePage is the share screen's view data, resolved in the handler rather
diff --git a/internal/docs/signin_door_test.go b/internal/docs/signin_door_test.go
index 8e557ed..1b87d6c 100644
--- a/internal/docs/signin_door_test.go
+++ b/internal/docs/signin_door_test.go
@@ -8,7 +8,7 @@ import (
"strings"
"testing"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
)
// The sign-in page is the Oficina door (estilo chrome): a card on the
diff --git a/internal/docs/signin_return.go b/internal/docs/signin_return.go
index 4bd40f4..d4a0047 100644
--- a/internal/docs/signin_return.go
+++ b/internal/docs/signin_return.go
@@ -36,7 +36,7 @@ import (
"amadan.net/oficina/home/handoff"
"amadan.net/oficina/home/handoff/seal"
- rauth "github.com/carlosframework/rastrillo/auth"
+ rauth "amadan.net/rastrillo/rastrillo/auth"
)
// standaloneReturn builds the standalone instance's return memory: the
diff --git a/internal/docs/stream.go b/internal/docs/stream.go
index abdc6c5..0e1a4c3 100644
--- a/internal/docs/stream.go
+++ b/internal/docs/stream.go
@@ -8,7 +8,7 @@ import (
"time"
"amadan.net/oficina/home/roster"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
)
// The stream's timings. Lifted from rastrillo's own SSE handler
diff --git a/internal/docs/team_access.go b/internal/docs/team_access.go
index 737510c..a3abbfa 100644
--- a/internal/docs/team_access.go
+++ b/internal/docs/team_access.go
@@ -6,7 +6,7 @@ import (
"net/http"
"amadan.net/oficina/home/roster"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
"gorm.io/gorm"
)
diff --git a/internal/docs/team_access_test.go b/internal/docs/team_access_test.go
index af6b6db..3782bb2 100644
--- a/internal/docs/team_access_test.go
+++ b/internal/docs/team_access_test.go
@@ -4,14 +4,14 @@ import (
"amadan.net/oficina/home/handoff/seal"
"amadan.net/oficina/home/roster"
family "amadan.net/rastrillo/rastrillo/crypto"
+ "amadan.net/rastrillo/rastrillo/migrate"
+ "amadan.net/rastrillo/rastrillo/sessions"
"bytes"
"context"
"encoding/base64"
"errors"
"github.com/carlosframework/docs/internal/docs/principalstore"
"github.com/carlosframework/docs/internal/docs/teamstate"
- "github.com/carlosframework/rastrillo/migrate"
- "github.com/carlosframework/rastrillo/sessions"
"gorm.io/gorm"
"io"
"net/http"
diff --git a/internal/docs/team_config.go b/internal/docs/team_config.go
index 4df74a3..33c2d6a 100644
--- a/internal/docs/team_config.go
+++ b/internal/docs/team_config.go
@@ -1,19 +1,19 @@
package docs
import (
+ "amadan.net/rastrillo/rastrillo/sessions"
"context"
"crypto/sha256"
"database/sql"
"encoding/base64"
"errors"
- "github.com/carlosframework/rastrillo/sessions"
"net/http"
"amadan.net/oficina/home/handoff/seal"
"amadan.net/oficina/home/roster"
+ "amadan.net/rastrillo/rastrillo/migrate"
"github.com/carlosframework/docs/internal/docs/principalstore"
"github.com/carlosframework/docs/internal/docs/teamstate"
- "github.com/carlosframework/rastrillo/migrate"
"github.com/go-json-experiment/json"
)
diff --git a/internal/docs/team_emission.go b/internal/docs/team_emission.go
index e7f209d..2605287 100644
--- a/internal/docs/team_emission.go
+++ b/internal/docs/team_emission.go
@@ -8,7 +8,7 @@ import (
"time"
"amadan.net/oficina/home/roster"
- "github.com/carlosframework/rastrillo"
+ "amadan.net/rastrillo/rastrillo"
"gorm.io/gorm"
)
diff --git a/internal/docs/team_home.go b/internal/docs/team_home.go
index e51efcb..682fe4d 100644
--- a/internal/docs/team_home.go
+++ b/internal/docs/team_home.go
@@ -5,8 +5,8 @@ import (
"net/http"
"amadan.net/rastrillo/rastrillo/assertion"
+ "amadan.net/rastrillo/rastrillo/sessions"
"github.com/carlosframework/docs/internal/docs/principalstore"
- "github.com/carlosframework/rastrillo/sessions"
)
// existingPrincipal is read-only; an existing browser session cannot cause an
diff --git a/internal/docs/team_home_test.go b/internal/docs/team_home_test.go
index 2cbf266..ddfe8e8 100644
--- a/internal/docs/team_home_test.go
+++ b/internal/docs/team_home_test.go
@@ -10,8 +10,8 @@ import (
"amadan.net/oficina/home/roster"
"amadan.net/rastrillo/rastrillo/assertion"
+ "amadan.net/rastrillo/rastrillo/sessions"
"github.com/carlosframework/docs/internal/docs/principalstore"
- "github.com/carlosframework/rastrillo/sessions"
)
func TestTeamCompletionCannotAllocateAroundCurrentAccount(t *testing.T) {
diff --git a/internal/docs/team_identity_test.go b/internal/docs/team_identity_test.go
index 1d37662..3929a70 100644
--- a/internal/docs/team_identity_test.go
+++ b/internal/docs/team_identity_test.go
@@ -10,9 +10,9 @@ import (
"amadan.net/oficina/home/roster"
family "amadan.net/rastrillo/rastrillo/crypto"
+ "amadan.net/rastrillo/rastrillo/migrate"
"github.com/carlosframework/docs/internal/docs/principalstore"
"github.com/carlosframework/docs/internal/docs/teamstate"
- "github.com/carlosframework/rastrillo/migrate"
"github.com/go-json-experiment/json"
"gorm.io/gorm"
)
diff --git a/internal/docs/team_router_test.go b/internal/docs/team_router_test.go
index 89d88ab..a2db9a0 100644
--- a/internal/docs/team_router_test.go
+++ b/internal/docs/team_router_test.go
@@ -20,8 +20,8 @@ import (
"amadan.net/oficina/home/roster"
family "amadan.net/rastrillo/rastrillo/crypto"
+ "amadan.net/rastrillo/rastrillo/sessions"
"github.com/carlosframework/docs/internal/docs/principalstore"
- "github.com/carlosframework/rastrillo/sessions"
)
type teamRouterDirectory struct {
diff --git a/internal/docs/team_session_reader.go b/internal/docs/team_session_reader.go
index ebd712c..c69e117 100644
--- a/internal/docs/team_session_reader.go
+++ b/internal/docs/team_session_reader.go
@@ -6,14 +6,14 @@ import (
"log/slog"
"net/http"
- canonicalSessions "amadan.net/rastrillo/rastrillo/sessions"
- "github.com/carlosframework/rastrillo/sessions"
+ "amadan.net/rastrillo/rastrillo/sessions"
)
-// Keep validation in the shared reader. Structural conversion fails to compile
-// if either framework version changes the fields carried by a session.
+// Keep validation in the shared reader: FromContext bounds the session
+// lookup by the caller's context. (Before Docs moved off rastrillo's
+// pre-move path, this converted between the two packages' Session types.)
func newTeamSessionReader(db *sql.DB, origin, cookieName string, logger *slog.Logger) (func(context.Context, *http.Request) (sessions.Session, bool), error) {
- reader, e := canonicalSessions.New(canonicalSessions.Config{DB: db, Origin: origin, Logger: logger})
+ reader, e := sessions.New(sessions.Config{DB: db, Origin: origin, Logger: logger})
if e != nil || reader.CookieName() != cookieName {
return nil, errTeamConfig
}
@@ -21,7 +21,6 @@ func newTeamSessionReader(db *sql.DB, origin, cookieName string, logger *slog.Lo
if _, present, ok := homeCookie(r, cookieName); !ok || !present {
return sessions.Session{}, false
}
- got, ok := reader.FromContext(ctx, r)
- return sessions.Session(got), ok
+ return reader.FromContext(ctx, r)
}, nil
}
diff --git a/internal/docs/team_session_reader_test.go b/internal/docs/team_session_reader_test.go
index 63daad9..1088568 100644
--- a/internal/docs/team_session_reader_test.go
+++ b/internal/docs/team_session_reader_test.go
@@ -7,7 +7,7 @@ import (
"testing"
"time"
- "github.com/carlosframework/rastrillo/sessions"
+ "amadan.net/rastrillo/rastrillo/sessions"
)
func TestTeamSessionReaderMatchesActualLegacySession(t *testing.T) {
diff --git a/internal/docs/team_stream.go b/internal/docs/team_stream.go
index 29d07cf..93e27fb 100644
--- a/internal/docs/team_stream.go
+++ b/internal/docs/team_stream.go
@@ -6,7 +6,7 @@ import (
"time"
"amadan.net/oficina/home/roster"
- "github.com/carlosframework/rastrillo/sessions"
+ "amadan.net/rastrillo/rastrillo/sessions"
)
type teamStreamGuard struct {
diff --git a/internal/docs/teamstate/store.go b/internal/docs/teamstate/store.go
index 00d016a..63ebb7b 100644
--- a/internal/docs/teamstate/store.go
+++ b/internal/docs/teamstate/store.go
@@ -9,7 +9,7 @@ import (
"errors"
"amadan.net/oficina/home/roster"
- "github.com/carlosframework/rastrillo/migrate"
+ "amadan.net/rastrillo/rastrillo/migrate"
)
//go:embed migrations/*.sql
diff --git a/internal/docs/teamstate/store_test.go b/internal/docs/teamstate/store_test.go
index 097ec5f..934ca1e 100644
--- a/internal/docs/teamstate/store_test.go
+++ b/internal/docs/teamstate/store_test.go
@@ -9,8 +9,8 @@ import (
"testing"
"amadan.net/oficina/home/roster"
- "github.com/carlosframework/rastrillo/db"
- "github.com/carlosframework/rastrillo/migrate"
+ "amadan.net/rastrillo/rastrillo/db"
+ "amadan.net/rastrillo/rastrillo/migrate"
)
func fixture(t *testing.T) *db.DB {
diff --git a/internal/docs/theme_assets_test.go b/internal/docs/theme_assets_test.go
index 55d3e16..95d1dbd 100644
--- a/internal/docs/theme_assets_test.go
+++ b/internal/docs/theme_assets_test.go
@@ -1,6 +1,7 @@
package docs
import (
+ "io/fs"
"path"
"amadan.net/oficina/estilo.git/busy"
@@ -13,7 +14,7 @@ import (
"testing"
"amadan.net/oficina/estilo.git/theme"
- "github.com/carlosframework/rastrillo/ui"
+ "amadan.net/rastrillo/rastrillo/ui"
)
func TestSharedThemeAssetFingerprintAndCache(t *testing.T) {
@@ -99,4 +100,20 @@ func TestBusyRuleIsLinkedAndServed(t *testing.T) {
t.Errorf("GET %s = %d or the wrong bytes", hashed, res.Code)
}
}
+ // No rastrillo script on disk. Docs serves them from memory
+ // (vendoredStaticFS); `rastrillo doctor --fix` copies the ones the
+ // library ships into a static/ it finds, and the shim it would copy
+ // still carries the old busy rule, which fights estilo's busy.js.
+ // Delete anything --fix adds.
+ for _, tree := range []fs.FS{staticFS, brandFS} {
+ _ = fs.WalkDir(tree, ".", func(name string, d fs.DirEntry, err error) error {
+ if err == nil && !d.IsDir() {
+ switch path.Base(name) {
+ case "rastrillo.js", "busy.js", "select.js", "datetime.js", "calendar.js", "tokens.css", "theme.css":
+ t.Errorf("%s is on disk; Docs serves rastrillo's and estilo's assets from memory, and doctor's shim would bring the old busy rule back", name)
+ }
+ }
+ return nil
+ })
+ }
}
diff --git a/internal/lint/no_premove_rastrillo_test.go b/internal/lint/no_premove_rastrillo_test.go
new file mode 100644
index 0000000..932105c
--- /dev/null
+++ b/internal/lint/no_premove_rastrillo_test.go
@@ -0,0 +1,69 @@
+package lint
+
+import (
+ "go/parser"
+ "go/token"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "testing"
+)
+
+// preMoveRastrillo is rastrillo's module path before it moved to
+// amadan.net/rastrillo/rastrillo. Nothing after v0.23.0 was released
+// under it, so code importing it gets no rastrillo fix, and its own
+// checks cannot tell: Docs zoomed iOS on every tap of every field for a
+// month after rastrillo fixed it (polish audit r3, item 1).
+const preMoveRastrillo = "github.com/carlosframework/rastrillo"
+
+// preMoveAllowed is the one file that may still import it, the one
+// package it may import, and why: rastrillo/native's server takes the
+// pre-move path's *sessions.Sessions. Delete the entry when
+// native/server moves.
+var preMoveAllowed = map[string]string{
+ "internal/docs/native.go": preMoveRastrillo + "/sessions",
+}
+
+// TestNoPreMoveRastrillo fails on any import of rastrillo's pre-move
+// module path outside preMoveAllowed.
+func TestNoPreMoveRastrillo(t *testing.T) {
+ root := repoRoot(t)
+ fset := token.NewFileSet()
+ err := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+ if d.IsDir() {
+ if path != root && skipDir(d.Name()) {
+ return filepath.SkipDir
+ }
+ return nil
+ }
+ if !strings.HasSuffix(path, ".go") {
+ return nil
+ }
+ f, err := parser.ParseFile(fset, path, nil, parser.ImportsOnly)
+ if err != nil {
+ return err
+ }
+ rel, err := filepath.Rel(root, path)
+ if err != nil {
+ return err
+ }
+ rel = filepath.ToSlash(rel)
+ for _, imp := range f.Imports {
+ p, err := strconv.Unquote(imp.Path.Value)
+ if err != nil {
+ return err
+ }
+ if (p == preMoveRastrillo || strings.HasPrefix(p, preMoveRastrillo+"/")) && preMoveAllowed[rel] != p {
+ t.Errorf("%s: imports %q, rastrillo's frozen pre-move path; use amadan.net/rastrillo/rastrillo", rel, p)
+ }
+ }
+ return nil
+ })
+ if err != nil {
+ t.Fatalf("lint: walk %s: %v", root, err)
+ }
+}
diff --git a/internal/lint/no_sessions_userid_test.go b/internal/lint/no_sessions_userid_test.go
index 09f8c3e..f6df02f 100644
--- a/internal/lint/no_sessions_userid_test.go
+++ b/internal/lint/no_sessions_userid_test.go
@@ -15,13 +15,17 @@ import (
"testing"
)
-// bannedSessionsUserIDPackage and bannedSessionsUserIDFunc identify
+// bannedSessionsUserIDPackages and bannedSessionsUserIDFunc identify
// the one call this repo's own code must never make. See
-// TestNoSessionsUserID's own doc comment for why.
-const (
- bannedSessionsUserIDPackage = "github.com/carlosframework/rastrillo/sessions"
- bannedSessionsUserIDFunc = "UserID"
-)
+// TestNoSessionsUserID's own doc comment for why. Both module paths:
+// native.go keeps one import of the pre-move package
+// (TestNoPreMoveRastrillo), and its UserID is the same trap.
+var bannedSessionsUserIDPackages = map[string]bool{
+ "amadan.net/rastrillo/rastrillo/sessions": true,
+ "github.com/carlosframework/rastrillo/sessions": true,
+}
+
+const bannedSessionsUserIDFunc = "UserID"
// repoRoot resolves the module root from this test's own directory —
// internal/lint, two levels below it — the same "../.." relative-path
@@ -123,7 +127,7 @@ func TestNoSessionsUserID(t *testing.T) {
dotImported := false
for _, imp := range f.Imports {
importPath, err := strconv.Unquote(imp.Path.Value)
- if err != nil || importPath != bannedSessionsUserIDPackage {
+ if err != nil || !bannedSessionsUserIDPackages[importPath] {
continue
}
switch {
diff --git a/scripts/build-release.sh b/scripts/build-release.sh
index d829974..65ecbd9 100755
--- a/scripts/build-release.sh
+++ b/scripts/build-release.sh
@@ -35,7 +35,7 @@ cd "$docs_source"
# an unrelated checkout it cannot read — and fails the build (2026-09-29).
CGO_ENABLED=0 GOOS="${GOOS:-linux}" GOARCH="${GOARCH:-arm64}" \
go build -mod=readonly -trimpath -buildvcs=false \
- -ldflags "-s -w -X github.com/carlosframework/rastrillo.BuildVersion=$docs_version" \
+ -ldflags "-s -w -X amadan.net/rastrillo/rastrillo.BuildVersion=$docs_version" \
-o "$docs_output" ./cmd/docs
echo "built $docs_output reporting version $docs_version"