Commit Graph
2902 Commits
Author SHA1 Message Date
github-actions[bot] fe0aa4c02c chore: bump version to 1.11.32 [skip ci] 2026-11-03 01:07:17 +00:00
Juan Denis b6fb6e7009 Merge pull request #192 from jhd3197/dependabot/pip/backend/dev/backend-f0b41e5f7e
build(deps): bump the backend group across 1 directory with 17 updates
2026-11-02 19:59:43 -05:00
github-actions[bot] d32cfac616 chore: bump version to 1.11.31 [skip ci] 2026-11-03 00:56:59 +00:00
dependabot[bot] 66c271a530 build(deps): bump the backend group across 1 directory with 17 updates
Bumps the backend group with 17 updates in the /backend directory:

| Package | From | To |
| --- | --- | --- |
| [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) | `2.0.52` | `2.0.55` |
| [flask-migrate](https://github.com/miguelgrinberg/flask-migrate) | `4.0.7` | `4.1.0` |
| [flask-jwt-extended](https://github.com/vimalloc/flask-jwt-extended) | `4.6.0` | `4.7.4` |
| [flask-cors](https://github.com/corydolphin/flask-cors) | `6.0.2` | `6.0.5` |
| [flask-socketio](https://code.miguelgrinberg.com/miguelgrinberg/flask-socketio) | `5.6.1` | `5.7.0` |
| [python-socketio](https://github.com/sponsors/miguelgrinberg) | `5.16.3` | `5.17.1` |
| [python-engineio](https://code.miguelgrinberg.com/miguelgrinberg/python-engineio) | `4.13.3` | `4.15.1` |
| [python-dotenv](https://github.com/theskumar/python-dotenv) | `1.2.2` | `1.2.4` |
| [pyyaml](https://github.com/yaml/pyyaml) | `6.0.1` | `6.0.3` |
| [click](https://github.com/pallets/click) | `8.3.3` | `8.5.0` |
| [croniter](https://github.com/pallets-eco/croniter) | `6.0.0` | `6.2.4` |
| [cryptography](https://github.com/pyca/cryptography) | `50.0.0` | `50.0.2` |
| [pyotp](https://github.com/pyauth/pyotp) | `2.9.0` | `2.10.0` |
| [requests](https://github.com/psf/requests) | `2.33.1` | `2.34.2` |
| [boto3](https://github.com/boto/boto3) | `1.35.0` | `1.43.123` |
| [apispec](https://github.com/marshmallow-code/apispec) | `6.4.0` | `6.10.0` |
| [prompture](https://github.com/jhd3197/prompture) | `1.11.0` | `1.16.0` |



Updates `sqlalchemy` from 2.0.52 to 2.0.55
- [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases)
- [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst)
- [Commits](https://github.com/sqlalchemy/sqlalchemy/commits)

Updates `flask-migrate` from 4.0.7 to 4.1.0
- [Release notes](https://github.com/miguelgrinberg/flask-migrate/releases)
- [Changelog](https://github.com/miguelgrinberg/Flask-Migrate/blob/main/CHANGES.md)
- [Commits](https://github.com/miguelgrinberg/flask-migrate/compare/v4.0.7...v4.1.0)

Updates `flask-jwt-extended` from 4.6.0 to 4.7.4
- [Release notes](https://github.com/vimalloc/flask-jwt-extended/releases)
- [Commits](https://github.com/vimalloc/flask-jwt-extended/compare/4.6.0...4.7.4)

Updates `flask-cors` from 6.0.2 to 6.0.5
- [Release notes](https://github.com/corydolphin/flask-cors/releases)
- [Changelog](https://github.com/corydolphin/flask-cors/blob/main/CHANGELOG.md)
- [Commits](https://github.com/corydolphin/flask-cors/compare/6.0.2...6.0.5)

Updates `flask-socketio` from 5.6.1 to 5.7.0

Updates `python-socketio` from 5.16.3 to 5.17.1
- [Commits](https://github.com/sponsors/miguelgrinberg/commits)

Updates `python-engineio` from 4.13.3 to 4.15.1

Updates `python-dotenv` from 1.2.2 to 1.2.4
- [Release notes](https://github.com/theskumar/python-dotenv/releases)
- [Changelog](https://github.com/theskumar/python-dotenv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/theskumar/python-dotenv/compare/v1.2.2...v1.2.4)

Updates `pyyaml` from 6.0.1 to 6.0.3
- [Release notes](https://github.com/yaml/pyyaml/releases)
- [Changelog](https://github.com/yaml/pyyaml/blob/6.0.3/CHANGES)
- [Commits](https://github.com/yaml/pyyaml/compare/6.0.1...6.0.3)

Updates `click` from 8.3.3 to 8.5.0
- [Release notes](https://github.com/pallets/click/releases)
- [Changelog](https://github.com/pallets/click/blob/main/CHANGES.md)
- [Commits](https://github.com/pallets/click/compare/8.3.3...8.5.0)

Updates `croniter` from 6.0.0 to 6.2.4
- [Release notes](https://github.com/pallets-eco/croniter/releases)
- [Changelog](https://github.com/pallets-eco/croniter/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pallets-eco/croniter/compare/6.0.0...6.2.4)

Updates `cryptography` from 50.0.0 to 50.0.2
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/50.0.0...50.0.2)

Updates `pyotp` from 2.9.0 to 2.10.0
- [Release notes](https://github.com/pyauth/pyotp/releases)
- [Changelog](https://github.com/pyauth/pyotp/blob/main/Changes.rst)
- [Commits](https://github.com/pyauth/pyotp/compare/v2.9.0...v2.10.0)

Updates `requests` from 2.33.1 to 2.34.2
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.33.1...v2.34.2)

Updates `boto3` from 1.35.0 to 1.43.123
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.35.0...1.43.123)

Updates `apispec` from 6.4.0 to 6.10.0
- [Changelog](https://github.com/marshmallow-code/apispec/blob/dev/CHANGELOG.rst)
- [Commits](https://github.com/marshmallow-code/apispec/compare/6.4.0...6.10.0)

Updates `prompture` from 1.11.0 to 1.16.0
- [Release notes](https://github.com/jhd3197/prompture/releases)
- [Commits](https://github.com/jhd3197/prompture/compare/v1.11.0...v1.16.0)

---
updated-dependencies:
- dependency-name: apispec
  dependency-version: 6.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: backend
- dependency-name: boto3
  dependency-version: 1.43.123
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: backend
- dependency-name: click
  dependency-version: 8.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: backend
- dependency-name: croniter
  dependency-version: 6.2.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: backend
- dependency-name: cryptography
  dependency-version: 50.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: backend
- dependency-name: flask-cors
  dependency-version: 6.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: backend
- dependency-name: flask-jwt-extended
  dependency-version: 4.7.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: backend
- dependency-name: flask-migrate
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: backend
- dependency-name: flask-socketio
  dependency-version: 5.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: backend
- dependency-name: prompture
  dependency-version: 1.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: backend
- dependency-name: pyotp
  dependency-version: 2.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: backend
- dependency-name: python-dotenv
  dependency-version: 1.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: backend
- dependency-name: python-engineio
  dependency-version: 4.15.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: backend
- dependency-name: python-socketio
  dependency-version: 5.17.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: backend
- dependency-name: pyyaml
  dependency-version: 6.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: backend
- dependency-name: requests
  dependency-version: 2.34.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: backend
- dependency-name: sqlalchemy
  dependency-version: 2.0.55
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: backend
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-03 00:52:04 +00:00
Juan Denis 327be8f685 Merge pull request #168 from jhd3197/dependabot/pip/backend/dev/websockets-16.1.1
build(deps): bump websockets from 15.0.1 to 16.1.1 in /backend
2026-11-02 19:49:23 -05:00
github-actions[bot] b54241c2b1 chore: bump version to 1.11.30 [skip ci] 2026-11-03 00:48:54 +00:00
dependabot[bot] 67a2e972db build(deps): bump websockets from 15.0.1 to 16.1.1 in /backend
Bumps [websockets](https://github.com/python-websockets/websockets) from 15.0.1 to 16.1.1.
- [Release notes](https://github.com/python-websockets/websockets/releases)
- [Commits](https://github.com/python-websockets/websockets/compare/15.0.1...16.1.1)

---
updated-dependencies:
- dependency-name: websockets
  dependency-version: 16.1.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-03 00:42:50 +00:00
Juan Denis 4c2f583225 Merge pull request #169 from jhd3197/dependabot/pip/backend/dev/gunicorn-26.2.0
build(deps): bump gunicorn from 23.0.0 to 26.2.0 in /backend
2026-11-02 19:41:24 -05:00
dependabot[bot] 07c0d7d4e3 build(deps): bump gunicorn from 23.0.0 to 26.2.0 in /backend
Bumps [gunicorn](https://github.com/benoitc/gunicorn) from 23.0.0 to 26.2.0.
- [Release notes](https://github.com/benoitc/gunicorn/releases)
- [Commits](https://github.com/benoitc/gunicorn/compare/23.0.0...26.2.0)

---
updated-dependencies:
- dependency-name: gunicorn
  dependency-version: 26.2.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-03 00:33:41 +00:00
github-actions[bot] 5d8328ce92 chore: bump version to 1.11.29 [skip ci] 2026-11-03 00:11:32 +00:00
Juan Denis 434c3458f6 Merge pull request #170 from jhd3197/dependabot/pip/backend/dev/marshmallow-4.3.1
build(deps): bump marshmallow from 3.26.2 to 4.3.1 in /backend
2026-11-02 19:04:53 -05:00
github-actions[bot] 6b90776e5a chore: bump version to 1.11.28 [skip ci] 2026-11-03 00:03:26 +00:00
dependabot[bot] 5b0b0550fc build(deps): bump marshmallow from 3.26.2 to 4.3.1 in /backend
Bumps [marshmallow](https://github.com/marshmallow-code/marshmallow) from 3.26.2 to 4.3.1.
- [Changelog](https://github.com/marshmallow-code/marshmallow/blob/dev/CHANGELOG.rst)
- [Commits](https://github.com/marshmallow-code/marshmallow/compare/3.26.2...4.3.1)

---
updated-dependencies:
- dependency-name: marshmallow
  dependency-version: 4.3.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-02 23:57:34 +00:00
Juan Denis 6fdf4f65a8 Merge pull request #191 from jhd3197/fix/registry-bundled-index
Re-sync bundled registry index and bump Authlib to 1.9.1
2026-11-02 18:56:23 -05:00
Juan Denis d723d887e7 Bump Authlib to 1.9.1 2026-11-02 18:49:06 -05:00
Juan Denis 2f41a9222f Re-sync bundled registry index with the published one 2026-11-02 18:36:38 -05:00
Juan Denis 2521da0e46 Add an SSH Access server permission profile
Faro access grants install keys through the agent's ssh:keys
actions. A locked-down server had no canned profile for that short
of Full Access; ssh_access grants ssh:keys:* plus the health reads.
2026-10-26 11:16:21 -04:00
Juan Denis cdd6d0898d Drop the unused schedule and passlib packages
Each survived as a single import nothing called: scheduling moved to
the job runner, and the FTP service never used sha512_crypt.
2026-10-26 01:44:23 -04:00
Juan Denis a9668000da Keep the new route logic behind services
The SSL-enable and server-overview changes put session and query
calls in the routes, tripping the controller-boundary ratchet. Move
them into SiteDomainService and WorkspaceService, raise a typed error
for bad allowed_ips, point the ACME-contact test at the new vhost
door, and regenerate the baseline and inventory (476 -> 453).
2026-10-26 01:43:12 -04:00
Juan Denis d2a83ce6a8 Make panel thread count configurable
Every open WebSocket and every long-polling agent holds one of the
single process's 100 threads, so ~60 agents plus 40 tabs stalled the
UI with no clear error. Read --threads from SERVERKIT_THREADS in the
systemd unit and Docker image, and document the ceiling next to the
single-worker constraint.
2026-10-26 01:05:49 -04:00
Juan Denis a8fb879be8 Stop the speed-test poll when leaving Monitoring
The wait loop kept polling for up to 90s after unmount and toasted
'Speed test complete' on whatever page came next.
2026-10-26 01:04:25 -04:00
Juan Denis e3131659c2 Satisfy the test seed ratchet
The custom-domain SSL test seeded its app by hand instead of through
make_application, and test_manifest_reach.py no longer seeds one, so
its baseline entry went stale.
2026-10-26 01:03:40 -04:00
Juan Denis f116accbb8 Map setup status in one place
checkSetupStatus and refreshSetupStatus kept separate copies of the
same mapping, and the refresh copy had already lost defaultLanguage.
2026-10-26 01:02:42 -04:00
Juan Denis 0704c42daa Drop unused useLogs and logsSourceLabel
Nothing imports either; useServiceLogStream replaced the hook, which
also left loading stuck on a read error.
2026-10-26 01:02:37 -04:00
Juan Denis 411ce694da Remove the orphaned manifest preview service
The generic preview provisioner replaced its only caller; only its
own tests still reached it, proving a path production no longer
takes.
2026-10-26 01:02:35 -04:00
Juan Denis 1fe8ada10d Look up agent registration tokens by digest
POST /servers/register needs no login and ran a slow PBKDF2 check
against every pending server per request, so a few IPs under the
5/min limit could keep the single worker's CPU busy. Tokens carry 256
random bits, so store a SHA-256 digest and find the row directly;
hashes issued before this still verify until they expire.
2026-10-26 01:00:48 -04:00
Juan Denis a915e95474 Send container log streams only to their viewer
Every subscriber starts its own docker logs process but emitted into
the shared app room, so with two viewers open each saw every line
twice, got the other's tail replayed, and both saw 'ended' when either
stream stopped. Deliver to the owning socket while room membership
still gates it, keeping the per-line access re-check.
2026-10-26 00:59:21 -04:00
Juan Denis c5d0597140 Make login-link redemption truly single-use
redeem() checked used_at, then set it and committed, so two requests
arriving together (a mail-preview bot and the user, or an attacker
racing them) both passed the check and both got a session. Claim the
link with one conditional UPDATE and refuse when no row changed.
2026-10-26 00:57:28 -04:00
Juan Denis 2dee9fa891 Pass DB passwords via env, not the command line
docker exec -e MYSQL_PWD=<pw>, mysqldump -p<pw> and friends put the
root DB password in argv, readable by every local account through ps
or /proc. Add secret_env() and hand the password to the child's
environment (bare -e NAME for docker exec), and drop it from the
mysqladmin readiness ping, which never needed it.
2026-10-26 00:56:42 -04:00
Juan Denis 83ea2c59d4 Write cron and storage settings atomically
Both files used a truncating open() and their loaders read damage as
empty, so a full disk mid-write reset off-site backups to local and
the next cron add replaced every job's metadata with the new job.
Route both through the config store's temp+replace write; an
unreadable file is moved aside instead of being overwritten.
2026-10-26 00:53:25 -04:00
Juan Denis a79d5010c2 Escape % in crontab commands
cron treats a bare % as end-of-command and pipes the rest to stdin,
so a job like 'date +%F >> log' ran as 'date +' on schedule while
Run now (bash -c) ran it correctly. Write lines with \%, unescape
when parsing, and locate a job's line by parsing in edit and
tracking so legacy unescaped lines are still found and fixed.
2026-10-26 00:51:38 -04:00
Juan Denis cb93120bac Keep custom-domain HTTPS across vhost rebuilds
Enabling SSL on a custom domain edited the vhost in place, but every
later rewrite (deploy, slot switch, domain attach, drift repair,
restore) rebuilt it from Domain rows that only knew wildcard certs,
so HTTPS silently disappeared while the row still said enabled.

Rebuilds now resolve each domain's own cert and render one server set
per certificate when domains differ. Enable/attach publish through
write_app_vhost and only claim SSL when nginx accepted it, the key
path is stored under its real column (legacy rows fall back to
certbot's privkey.pem), disable drops the HTTPS block, and a repeat
add_ssl_to_site swaps the cert instead of breaking nginx -t.
2026-10-26 00:49:57 -04:00
Juan Denis cb1422f34f Log out only when the refresh token is rejected
Any failed refresh (offline, 5xx, 429) cleared both tokens, and each
expired request started its own refresh, so a burst of 401s could
trip the refresh rate limit and log the tab out. Page load also wiped
tokens on any /auth/me failure. Share one in-flight refresh, end the
session only on a 401/422 from /auth/refresh or /auth/me, and let
transient failures surface as errors with the tokens intact.
2026-10-26 00:46:13 -04:00
Juan Denis f724cf0067 Keep live sockets alive past access-token expiry
Every emit re-validated the socket's saved JWT including exp, and
access tokens last 15 minutes, so metrics, terminals, logs and
notifications were cut a quarter-hour after connecting; clients do
not reconnect after a server-side disconnect. Re-checks now skip exp
only; revocation, auth_version and deactivation still end the socket,
and connecting still needs an unexpired token.
2026-10-26 00:44:28 -04:00
Juan Denis 475add2674 Validate Postgres helper SQL and report user errors
pg_create_database/user and pg_grant/revoke built superuser SQL from
raw names and passwords, unlike the MySQL helpers beside them. A quote
in a password broke CREATE USER, and the create routes ignored that
and returned credentials for a user that did not exist. Validate
identifiers and privilege lists, escape the password, and surface a
failed user as user_error instead of fake credentials.
2026-10-26 00:43:13 -04:00
Juan Denis 84d6cdef4c Block file ops on parents of protected roots
PROTECTED_ROOTS only matched the path the user typed, so copying /opt
copied /opt/serverkit/.env (JWT key, DB creds) somewhere readable,
and deleting or moving /opt took the running panel with it. Refuse
copy, move, rename and delete when a protected root lies inside the
source, and keep symlinks as links when copying a tree.
2026-10-26 00:39:26 -04:00
Juan Denis e1835149a7 Require a verified email before SSO account linking
find_or_create_user attached a new SSO identity to any user with the
same email, but Google and generic OIDC profiles never carried
email_verified. An IdP account showing an unverified copy of the
admin's address signed in as the admin. Carry the claim through and
refuse to link without it; GitHub and SAML already vouch.
2026-10-26 00:37:57 -04:00
Juan Denis 8ab5ab1bfc Stop SSO from auto-creating developer accounts
Auto-provision defaulted on with role developer and no domain filter,
so enabling GitHub login for yourself let any GitHub user sign up and
open remote terminals, while password registration stayed closed.
Default to off and viewer; turning it on stays an explicit choice.
2026-10-26 00:36:57 -04:00
Juan Denis 9b85952b5f Enforce workspace access on every server route
Only three routes checked can_access_server; the rest loaded the server
by id, so a developer outside a workspace could run cron, write files,
install packages or widen agent permissions on its servers, and the
list/overview/docker picker showed every server. Every <server_id>
route now resolves through the workspace check, lists filter in SQL,
and PUT /servers/<id> validates allowed_ips like PUT /allowed-ips.
A sweep test walks the URL map so a new unguarded route fails CI.
2026-10-26 00:35:55 -04:00
Juan Denis 26e2d8c44c Merge main into dev to rejoin the histories [skip version]
main received dev's work through squash merges, so the two branches had
diverged and VERSION conflicted on the promotion PR. The tree is dev's
unchanged; this only records main as an ancestor.
2026-10-26 00:02:23 -04:00
github-actions[bot] 2862becc4f chore: bump version to 1.11.27 [skip ci] 2026-10-26 03:35:00 +00:00
Juan Denis b1260f7ea5 Catch plan citations at commit time
The guard only ran inside a backend pytest shard, so a citation in
SCSS or JSX surfaced minutes after the push. The pre-commit hook now
runs the same test file in --staged mode on every staged app file,
reusing its patterns and PENDING allowlist so the two cannot drift.
2026-10-25 23:27:21 -04:00
Juan Denis 7249d2247b Drop plan citations from the controls styles 2026-10-25 23:27:17 -04:00
Juan Denis d4b8497630 Keep the PR title out of the create-pr body file
Agents opened PRs with --body-file on a file that began with the
title heading, so every PR description repeated its title. The title
now goes to its own .title.txt and the body file starts at the summary.
2026-10-25 23:18:24 -04:00
Juan Denis f2f9ec7267 Polish stepper rail and radio card selection
The vertical stepper rail floated between steps instead of joining the
markers, and the current step borrowed the focus ring. Radio cards
showed a radio dot beside the icon; the card already marks selection,
so the radio becomes a check badge in the corner.
2026-10-25 23:18:24 -04:00
Juan Denis 7c8519772f Add accessible form controls and field wiring
FormField now hands its control the id, aria-describedby, aria-invalid
and aria-required through context, so every settings form announces
its hint and validation without per-call wiring. IconButton gets a real
tooltip instead of title=, ProgressBar is a labelled progressbar with
tones and an indeterminate state, and Button takes `loading` without
changing width.

New controls the panel lacked: NumberField, Combobox (single, multiple,
creatable), TagInput, Calendar with DatePicker and DateRangePicker,
PinInput, Slider, RadioGroup, Stepper, TreeView, and FileDropzone with
FileUploadList. Rounding, date and file-type rules live in lib/ with
unit tests. All of them render on /style-guide/controls.
2026-10-25 23:18:24 -04:00
darren 228cfbf92f fix: show remote images by name, size and date on the server Docker tab (#186) 2026-10-25 23:18:07 -04:00
6e096fa286 Add real preview deployments and strengthen core boundaries (#184)
* fix(security): honour the failed-login time window (#180)

check_failed_logins computed a cutoff from since_hours and never used
it, so the Security -> Events "Failed login attempts (24h)" card and
its alert counted every failure still in /var/log/auth.log or
/var/log/secure: up to a week of SSH attempts under the usual weekly
log rotation.

Each matching line is now dated from its stamp, either RFC 3339
(rsyslog's high-precision format) or the traditional BSD syslog stamp
(no year, so a December line read in January is placed in the previous
year), and lines older than the cutoff are skipped. A line whose stamp
is not recognised is still counted rather than hidden. The log paths
move to SecurityService.AUTH_LOGS so the tests can point at a temp
file.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* refactor: separate backend startup phases and guard ordering

* refactor: route file operations through capability-checked adapters

* chore: bump version to 1.11.25 [skip ci]

* refactor: split File Manager state and views with regression guards

* test: enforce core boundaries and document extension rules

* test: cover File Manager tree races and listing failures

* fix: preserve File Manager deep links on initial mount

* refactor: keep File Manager download operations in the action hook

* fix: start agent maintenance only in the guarded runtime phase

* test: capture nginx rendering contract before extraction

* refactor: separate nginx configuration rendering from host operations

* test: enforce pure nginx configuration boundaries

* fix: require provisioned runtime before advertising previews

* feat: expose value-free effective environment provenance through app access boundary

* feat: add effective environment inspector with browser regression checks

* feat: provision isolated generic previews with retryable resource cleanup

* feat: queue preview automation and preserve cleanup ownership through app deletion

* feat: add pinned preview deployment controls and queued lifecycle feedback

* fix: preserve container port semantics for previews of slot deployments

* fix: preserve search focus and ignore stale list responses

* feat: run approved assistant deployments through persistent recipe operations

* test: run search and assistant deployment regressions in CI

* fix: refresh preview API and controller boundary inventories

* docs: refresh controller migration count after preview extraction

* fix: bind file editor previews to their storage target

* chore: bump version to 1.11.26 [skip ci]

---------

Co-authored-by: Max Freedom Pollard <272618364+MaxFreedomPollard@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-10-24 15:31:39 -04:00
github-actions[bot] a3b890af00 chore: bump version to 1.11.26 [skip ci] 2026-10-24 19:08:49 +00:00
Juan Denis d00c4a72ea fix: bind file editor previews to their storage target 2026-10-24 15:00:57 -04:00