Repository navigation
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012TKZy6f5shPzM9WLdswH6f
A bake started from POST /api/admin/bake now lands on the `unstable`
channel, which no buyer gets. POST /api/admin/bake/{id}/promote (called by
the harness after a green smoke clone) moves it to `latest`; the previous
`latest` becomes `stable`. Clone and validate resolve `latest`, then
`stable`, then the newest ungated snapshot, so stacks baked before this
change (and by the `bake` binary) keep working.
- migration: baked_snapshot_channels (pointer per stack/provider/channel),
baked_snapshots.gated, Casbin rule for the promote route
- db::bake_registry: point, state, promote (one transaction, pointers
locked; only the current `unstable` can be promoted; a repeat is a no-op)
- `gated` keeps a bake whose smoke failed hidden after the next bake
replaces the `unstable` pointer
Tests: tests/bake_channels.rs (written failing first).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
POST /api/admin/bake accepted any deployment whose server is in the platform's Hetzner project. Quick Deploy buyers' servers live there too, and sanitizing wipes the box (SSH host keys, .env, data volumes) before snapshotting it, so a mistyped deployment_id could wreck a buyer's server and put its data into a published snapshot. - the deployment must belong to the caller (403 otherwise); a service token (admin_service) owns no box and is refused. The bake harness calls with the CLI token of the admin who deployed the box, so it is unaffected - a deployment with a Managed-server usage row (Quick Deploy) is refused (409), even when the caller made it - the health probe no longer follows redirects: the box chooses where they point, and the backend would call that address for it Tests: tests/admin_bake.rs (another user's box, a Quick Deploy server, admin_service; the old code accepted the first with 202) and a unit test for the redirect, both written failing first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The smoke clone goes through POST /api/v1/deploy/clone, which serves only latest/stable. A fresh bake sits on unstable, so the smoke could never find it and nothing would ever be promoted. clone takes an optional `channel: "unstable"`, for group_admin only (403 otherwise, 400 for any other channel). It resolves exactly the bake the unstable pointer holds, with no fallback to a released snapshot. Buyers who omit it are unaffected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every spawned test app creates its own database (~11 MB with the
migrations) and nothing dropped them. A full CI run filled the runner's
disk until Postgres panicked ("could not write to file pg_wal/...: No
space left on device") and the last few hundred tests failed with
"Failed to start test app", on every branch.
configure_database (integration and BDD harnesses) now registers each
database it creates, and an atexit handler drops them all with
DROP DATABASE ... WITH (FORCE) when the process exits. Most apps live in
a static shared by a test file, so a Rust Drop would never run; process
exit is the end of each test under nextest and of each binary under
cargo test. The drop runs on a fresh thread: at exit the main thread's
thread-locals, which tokio needs, are gone.
Regression test: tests/test_databases_are_dropped.rs runs a child test
process that spawns an app, then checks its database is gone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tests: a test process drops the databases it created
BUGS: stacker install writes no .env (.env.example defaults missing)
…ovided keys flagged as regenerated (#14) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bake only the caller's own build box; no redirects in the health probe
Bake channels: a bake reaches buyers only after its smoke clone passes
Every auth method was instrumented with the whole ServiceRequest as a span field. Its Debug output lists every header and the query string, so each request wrote bearer, cookie, agent and MCP query tokens into the JSON log at info level; anyone reading the logs could replay them. The spans now record no arguments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012TKZy6f5shPzM9WLdswH6f (cherry picked from commit 61517cee0e698fc3245ed3d2f64df9c97e1fb291)
Keep credentials out of the auth spans
`channel: "unstable"` was allowed only for role `group_admin`. `root` inherits `group_admin` in Casbin, so the same admin who can POST /api/admin/bake got 403 on the smoke clone of that bake (seen on production), and the bake could never be promoted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ress fetch_user returned a shared `test_user_id` (role group_user) for any bearer token when the request to the auth server failed and auth_url was loopback or contained "localhost" - which Settings::default() is. Any string in `Authorization: Bearer` then acted as that one account. The branch was a test convenience compiled into production; the test harness runs its own /me mock and never needed it. Now it is the same error as for any other address, and the middleware refuses the request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
get_configuration fell back to Settings::default() whenever the configuration failed to deserialize, silently: auth at localhost, the database at 127.0.0.1. A typo in a production configuration.yaml would start a service on those defaults. A configuration that is there but does not parse is now an error. With no configuration file at all the defaults still apply: CI and the test harness run that way (configuration.yaml.dist is not read - `with_name` does not recognise the `.dist` extension). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Quick Deploy clone: a root admin may smoke-clone an unpromoted bake
OAuth: an unreachable auth server refuses the token, whatever its address
Configuration: a file that does not parse stops the service
The marketplace vendor profile accepted a free-form avatar_url and served it verbatim on the public author page, so a vendor could put an arbitrary external image URL on a page other users visit. avatar_url is now always derived from the account email via Gravatar (d=identicon), the client value is ignored, and a migration NULLs non-Gravatar values already stored (the next profile save fills in the derived URL). website_url, rendered into an <a href>, now rejects non-http(s) schemes.
Vendor avatar is derived via Gravatar; website_url must be http(s)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.