diff --git a/CHANGELOG.md b/CHANGELOG.md index 892395ea..4af93057 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,84 @@ All notable changes to Druks. Versions follow [semantic versioning](https://semver.org); while Druks is pre-1.0, a minor bump may break compatibility. +## [0.3.0] — 2026-08-22 + +### Added + +- **Logged-in browser sessions.** An extension declares the browser session a + site needs, and the operator signs in once through a Druks-hosted login window + — real Chrome over noVNC, opened on the site itself, with an optional timezone + and an egress proxy (authenticated if needed) for sign-ins that reject + datacenter IPs. A workflow then borrows that authenticated browser; the login + is encrypted, stored the first time a run reaches for it, and reused across + runs, and a session set to persist saves its refreshed state after each borrow. +- **OAuth connections.** You can sign in to an OAuth service more than once, and + Druks keeps each account as its own connection — one per mailbox, handle, or + workspace, owned by the account that consented and labeled with the provider's + own facts. A Connections page in Settings lists them; disconnecting keeps the + row as a revoked, auditable record rather than deleting it, and a repeat + sign-in reuses the matching connection instead of duplicating it. Extensions + build on one engine, `OauthClient` in `druks.services`, which runs the + authorization-code-with-PKCE flow with token caching and refresh; MCP sign-ins + ride the same engine. +- **Installed apps in the shell.** Every installed app appears in the dashboard + navigation and renders inside the shell instead of a separate page. An app with + a frontend ships an ESM `entry.js` and declared tabs and borrows the shell's + React, components, markdown renderer, and gate controls; an app with no + frontend still gets pages for free — a home page that stacks its subject + boards, and a subject page with summary facts, the run timeline, the latest + transcript, and gate controls. +- **Scheduled workflows can dispatch.** A workflow on a cron cadence can declare + a `dispatch()`; the schedule fires it instead of `run()`, so a subject-backed + workflow resolves its subject and starts the real run without a shim. + +### Changed + +- **Deployment is one profiled compose file.** Every service lives in a single + `compose.yaml`, with a `hosted` profile for the edge and janitor and a + `gateway` profile for the SSH gateway, so provider choice is a matter of + profiles and `.env`. `SERVICE_TOKENS` renders on every shape with no compose + default, so a missing token stops the sandbox plane instead of it starting on a + known one, and `install.sh` seeds an empty `compose.override.yaml` it never + overwrites, so host-local services survive installs and upgrades. +- **A service keys on a derived slug.** A service no longer declares a name or + title; the slug comes from the class name — `GoogleCalendar` becomes + `google_calendar` — and the card heading derives from it. The wire field and + connect route (`/api/services/{slug}`) follow, and an extension that still + declares `name` or `title` is rejected at load. +- **Board reads know the calling account.** A board scopes its rows to the + operator reading it, a subject carries a readable label, and a subject page and + the free board lead with the subject's type and name — `pull request: + owner/repo#7` — instead of a bare id. +- **One control frame across the shell.** The accent color reaches every surface, + and the status glyph pulses whenever any run is still going. +- **MCP tool names derive from `operation_id`.** An agent-tagged route gives an + unprefixed `operation_id`, and Druks prefixes it with the extension name, so an + author no longer writes the prefix by hand. +- **An app's subjects are checked at load.** A declared subject must supply a real + read-side; the loader rejects the platform stub and fails the boot instead of + the first request. +- **An approved, clean PR merges directly** instead of looping back through the + work gate; only a PR with unmet requirements falls back to auto-merge. + +### Removed + +- **The per-shape compose files.** `compose.local.yaml` and `compose.remote.yaml` + fold into the one profiled `compose.yaml`; `install.sh` removes the retired + overlays on upgrade. + +### Fixed + +- **Connect forms draw every declared field.** A bool, int, `Literal`, or + multiline field renders through the shared field component wherever it appears, + instead of falling back to a free-text box, and the replace placeholder + reflects the stored secret. +- **A spend-controlled Codex plan reports its quota as a weekly window** instead + of reading as a parse failure. +- **Sandbox provisioning failures retry.** A transient provisioning error is now + classified as transient, so the in-run retry covers it. +- **The app engine pool is sized for the run queue**, not a single request. + ## [0.2.0] — 2026-08-10 ### Added diff --git a/pyproject.toml b/pyproject.toml index 9e4b2290..b120e214 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "druks" -version = "0.2.0" +version = "0.3.0" description = "Autonomous software delivery; the self-hosted home for durable agent apps." readme = "README.md" license = "MIT" diff --git a/uv.lock b/uv.lock index 61092c2d..a2cac6fc 100644 --- a/uv.lock +++ b/uv.lock @@ -534,7 +534,7 @@ wheels = [ [[package]] name = "druks" -version = "0.2.0" +version = "0.3.0" source = { editable = "." } dependencies = [ { name = "alembic" },