You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
tango shell: a Go prompt on your project's models and database, with nothing served. It is a Yaegi interpreter (pinned at v0.16.1) run by the project's own shell/main.go through the new shell package, so the server never links it. Helpers Models, Describe, Get, List, Count, Create, Update and Delete work on any registered model addressed as app.Model, with plain-map queries and rows; -c EXPR and piped input make it scriptable; --readonly refuses writes; Options.Helpers adds your own functions as project.Name. At a terminal it has line editing, per-project history under your cache directory (TANGO_SHELL_HISTORY=off disables it), and Ctrl-C that clears the line, or ends a running evaluation with status 130. It says what Go the interpreter cannot run (min, max, clear, some generics, ranging over a function or an integer) and keeps the session through errors and panics. It runs your code with your project's credentials; it is not a sandbox. See the shell guide, ADR 0048 and ADR 0005. Adds github.com/traefik/yaegi to the root module; only a binary that imports shell links it.
admin.WithTrustedProxies and accounts.WithTrustedProxies: behind a reverse proxy, the failed-attempt limiters count the client address your proxy saw (the rightmost X-Forwarded-For entry outside the networks you name) instead of the proxy's own, so users no longer share one bucket. Opt-in: without it nothing is read from X-Forwarded-For and behaviour is unchanged, and only requests from the named networks may supply a forwarded address. The limiter also no longer keeps an entry for an address that has no recent failure. See behind a reverse proxy.
Running more than one instance: what is shared across instances (sessions, accounts, tokens), what is per process (the login limiter, ratelimit, realtime rooms, the accounts mail outbox and cooldown) and the workarounds, with ADR 0047 recording that shared state is not built yet and what would reopen it. No API changes.
A tango tui guide, with screens checked against the code by a test, and the promise about the dashboard in versioning and compatibility: the command, its terminal requirement, confirmation before database changes and delegation to the supported operations are covered; layout, wording and key bindings are not.
Changed
tango newproject writes two more directories. project/project.go holds func Config(store *db.Store) tango.Config: the installed apps, middleware and ordinary configuration that main.go used to build inline, so the server and the shell register the same apps from one list. main.go opens the database, builds the store and calls project.Config(store). shell/main.go is the program tango shell runs. tango newapp now says to install a new app in project/project.go when that file exists. Existing projects keep working as servers; to get a shell they follow the documented upgrade, a diff tested against the scaffold as it was before (ADR 0048).
The tutorial and the examples/board project list their apps in project/project.go; the board's token service and live feed are built inside project.Config, which stops the process with their error message when they cannot start.
tango admin create and tango admin resetpassword use TANGO_ADMIN_PASSWORD when it is set and non-empty, with no prompt. It was documented but never read. The value is never printed; the command names the variable instead.
tango migrate says what it did: applied 2 migrations: admin/0001_auto_…, blog/0002_auto_…, or no pending migrations, instead of always printing migrations applied. A project gets the new wording when it is built against this version; the rollback line is unchanged.
tango newproject ends with the real first-run order (tango makemigrations, tango migrate, tango admin create <username>), and the generated project prints admin: http://localhost:8000/admin/ after listening on (not with --no-admin). Existing projects are unchanged.
tango tui:
the greyed-out "Shell" item is gone;
"Apply pending migrations" and "Roll back the latest migration" grey out with a reason when status shows they cannot run (nothing to apply, nothing to roll back, or project status incomplete);
the confirmation prompts say what they will do.
Security
ratelimit.RemoteIPKey(trustedProxies...) could be made to give a client the key it chose. It took the leftmost X-Forwarded-For entry, which the client writes when the proxy appends to the header (nginx's default), and it did not check that the value was an IP address, so a client behind a trusted proxy could rotate its key to evade a limit or flood the limiter with new keys. It also fell back to X-Real-IP. It now reads X-Forwarded-For only from a trusted peer, parses every entry as an IP address, walks the list from the right skipping trusted proxies, and takes the first other address, which is the one your nearest trusted proxy saw. X-Real-IP is ignored, and a valid address is returned in canonical form. Unusable data falls back to the peer's address. The failed-login limiters of admin and accounts (admin.WithTrustedProxies, accounts.WithTrustedProxies) use the same resolver. This changes behaviour under the compatibility promise's security exception.
Upgrade: nothing changes without trusted proxies. With them, check that your proxy adds the address it sees to X-Forwarded-For (appending and replacing both work; passing the header through untouched does not). If you relied on X-Real-IP, make the proxy put the client address in X-Forwarded-For. Keys for IPv6 clients are now lower-case and compressed, and IPv4-mapped IPv6 addresses are keyed as IPv4, so a limit that was counted under the old spelling restarts once.
Fixed
tango admin create and resetpassword no longer show the password as you type it on a terminal. Piped input is read as before. This adds golang.org/x/term to the root module (ADR 0046).
Ctrl-C leaves tango tui even while a confirmation is showing; it used to be ignored until you answered.
Projects created by tango newproject now shut down gracefully: the generated main.go calls tango.ServeContext under signal.NotifyContext for Ctrl-C and SIGTERM, so in-flight requests finish and registered Lifecycle components stop. It called tango.Serve, which never reacts to a signal. Existing applications are unchanged; swap in ServeContext as the application lifecycle guide shows.
tango tui no longer ends the session when an apply or rollback fails. It shows Last action failed: … with the exit code and the command's last error line, refreshes the status, and returns to the menu; if the refresh also fails, both errors show.
Stopping the server started from tango tui with Ctrl-C or SIGTERM is a clean stop: tango waits for the server, prints server stopped and exits 0. It used to die with the signal. A server that fails, or exits with no signal, keeps its exit code.
tango tui explains a status failure (run tango check; an older main.go may need tango.DispatchFlags) before the raw error, which is kept.