v0.0.1-alpha.25
Pre-releaseOvercast v0.0.1-alpha.25
Docker Images
Full image with the web management console:
- Pull:
ghcr.io/neaox/overcast:0.0.1-alpha.25 - Channel tag:
ghcr.io/neaox/overcast:alpha - Registry: overcast package
Headless slim image for CI pipelines:
- Pull:
ghcr.io/neaox/overcast-slim:0.0.1-alpha.25 - Channel tag:
ghcr.io/neaox/overcast-slim:alpha - Registry: overcast-slim package
docker run --rm -p 4566:4566 -p 4567:4567 ghcr.io/neaox/overcast:0.0.1-alpha.25
docker run --rm -p 4566:4566 ghcr.io/neaox/overcast-slim:0.0.1-alpha.25Native Binaries
Download a binary for your platform from the assets below and verify it with SHA256SUMS.
| Asset | SHA256 |
|---|---|
overcast-darwin-amd64 |
9f45e9636ed07b0633cc66de7a0685f3182c3c0c43416e898dfc47d9d5627c49 |
overcast-darwin-arm64 |
2e154c58d747aba0d41bfeec72b7ab0b2f90f31f8677a6cf56c97cd8727e32b1 |
overcast-linux-amd64 |
f7a7d14df0a04c6b7f61b04d18c0c502bf1d20d4a2253aa8ea8c87f4d6504a24 |
overcast-linux-arm64 |
4acb7bd60d99a98a0b0f51c38c71b278831f3d442b21d6e17f3053ba27c3b0ca |
overcast-windows-amd64.exe |
1aa1eb4787aa3801026a9909c636a2242cd1839065e91c68aae0d00704734d9f |
overcastd-darwin-amd64 |
4d3bec857f4fdd6c3082ec8d081608c6122f249481e8ba707231de42e7b61e14 |
overcastd-darwin-arm64 |
478f15bd2b13619a6d32c928864c1aac47a9d94e0fd85ee5e89719e3faba4819 |
overcastd-linux-amd64 |
6ca8ff5316f5056eed301ef2b96e12aace09196c2ea34a3d0899510226946c76 |
overcastd-linux-arm64 |
d7e62bf96ee01e362edcaad0226dc5022c8468f2381aed4cbed708b530cb35e9 |
overcastd-windows-amd64.exe |
412ae446094197071eaa70f8c4e6cd8e35eb7ced0f45020bc5a7e89696dcb2ce |
Release Notes
Added
-
Networking — real AWS Host-routed (subdomain) addressing now works alongside path-style URLs, via a shared host-route dispatch table (
internal/middleware/hostroute.go): API Gateway invoke ({apiId}.execute-api.{region}.<base>, both REST v1 stage-prefixed and HTTP v2$default/named-stage forms), a brand-new Lambda function URLs feature (CreateFunctionUrlConfig/Get/Update/Delete/ListFunctionUrlConfigsplus Host-routed invocation mapping the request to the payload-v2.0 event shape;AuthTypeis stored but not enforced, matching Overcast's non-security-boundary stance), and AppSync GraphQL ({apiId}.appsync-api.{region}.<base>/graphql, also covering the colocated/realtimeendpoint). See docs/networking.md for the wildcard-DNS (*.localhost.overcast.sh) setup story and its offline caveats. -
Diagnostics —
GET /_debug/metricsand the Metrics & Health page's new "Storage Activity" card report cumulative storage-layer reads/writes since process start for every backend (memory, persistent, WAL, hybrid); ahybrid-mode store additionally breaks reads down by which tier actually served them (memory vs. a fall-through to SQLite) and shows how many accepted writes have been flushed to disk so far. -
Events — resource lifecycle events (SQS queues, S3 buckets, DynamoDB tables, SNS topics/subscriptions, Lambda functions, and most other resource-create/delete/update events) now carry the resource's ARN on the event envelope (
resourceArnin the SSE stream and MCP event feed); the web UI's Event Stream page auto-links any ARN it finds — the new field, or one embedded anywhere in a payload/error string — to that resource's page for every service that has one. -
CloudFormation —
RollbackStackis now supported, socdk rollbackcan recover a stack that a failed deploy left stuck: a stack inUPDATE_FAILEDorUPDATE_ROLLBACK_FAILEDrolls forward throughUPDATE_ROLLBACK_IN_PROGRESStoUPDATE_ROLLBACK_COMPLETE, and aCREATE_FAILEDstack unwinds throughROLLBACK_IN_PROGRESStoROLLBACK_COMPLETE, emitting the usual stack events along the way; previously the operation returned 501 and a failedcdk bootstrap/cdk deployleft the stack permanently un-deployable, since the CDK CLI refuses to retry until the stack is rolled back. Any state without a stable state to return to (CREATE_COMPLETE,UPDATE_COMPLETE, in-progress states) is rejected with the AWS-accurate 400ValidationError. Note that Overcast keeps no snapshot of each resource's pre-update properties, so a rollback restores the stack's status and retires resources left in a failed state rather than reverting individual resource configuration. -
S3 — virtual-hosted-style addressing now recognises
localhost.overcast.shandlocalhost.localstack.cloudas base hostnames with no configuration (both are wildcard-DNS domains resolving to 127.0.0.1), so an SDK or CDK pointed at either resolves buckets correctly out of the box;OVERCAST_HOSTNAMEstill works and now adds to those defaults rather than replacing them, and bases are matched longest-first so a configured parent domain cannot shadow a longer default. When a request still looks virtual-hosted against an unrecognised base, the server now logs a warning (once per distinct host) naming the received Host, the configuredOVERCAST_HOSTNAME, and the fix — previously the bucket was silently not extracted, the request stayed path-style, and the object key was then parsed as the bucket name, producing a confusing "bucket name is not valid" error naming the key rather than the real problem. -
Web UI — the console is restyled to the Overcast brand design system: brand colour tokens and JetBrains Mono throughout, working in both light and dark themes (including a theme-aware
favicon.svgthat followsprefers-color-scheme), a 228px sidebar and 52px topbar, breadcrumbs that omit the current page since its heading already names it, a search box that is present on every page and ranks results from the service you are currently viewing first, and a dashboard that groups services by how completely they are emulated (fully/partially/not emulated) with a grid-or-list view toggle that persists between visits. Every service list page now shares one layout — a card-wrapped table with mono column headers, a per-row type icon, consistent row actions, and the same Docs/Raw state/Refresh/Create header ordering — so pages no longer each invent their own. The command palette follows suit: service icons are monochrome, pin stars are always visible rather than appearing on hover, and services the emulator has disabled are greyed out and non-navigating instead of looking available. Typography now follows the brand rule throughout (JetBrains Mono for headings, labels, badges, table bodies and identifiers; the system sans for prose), and the dashboard no longer files a running service under "not emulated" merely because its emulation tier is incomplete. Lists now load into static skeleton rows rather than a centred spinner; dialogs gained a header/body/footer anatomy and the⏎ to create · esc to cancelcontract they previously only advertised; toasts gained a pending variant, so a slow upload or deploy reports progress instead of nothing; and an emulator that is configured but unreachable now shows a connecting screen with a retry, where it previously rendered nothing at all.
Fixed
-
S3 — virtual-hosted-style addressing (bucket name in the
Hostheader, e.g.bucket.s3.localhost:4566) now also recognises the legacy dash-region dialectbucket.s3-<region>.<base>(e.g.bucket.s3-us-west-2.amazonaws.com); it previously mis-extracted the bucket name asbucket.s3-<region>instead ofbucket, breaking every request. Added integration-level pinning coverage (previously unit-test-only) confirming the existing.s3./plain-.localhost/OVERCAST_HOSTNAMEforms already route correctly end-to-end through the real router, including dotted bucket names, nonexistent-bucket/key error fidelity (NoSuchBucket/NoSuchKey), and sub-resource calls (?location). -
Wire protocols — JSON-protocol services using the shared request decoder now reject an unparseable request body with 400
SerializationException, matching real AWS (DynamoDB-style coral services and Smithy's malformed-request protocol tests), instead of the non-AWSInvalidArgumentcode; five services (Kinesis, Backup, CloudTrail, Transfer, ECS) already returned the correct code via local variants and are unchanged. -
AppSync, API Gateway — request header names reach resolvers and integration events with AWS's casing rather than Go's. Go canonicalises incoming header names, so a client's
x-api-keyarrived asX-Api-Key, and that casing was copied verbatim into the VTL and JS resolver contexts, the direct Lambda resolver event, and the Lambda authorizer'srequestHeaders. AppSync documentsctx.request.headersin lowercase and VTL map access is an exact lookup, so a resolver written from the AWS docs as$ctx.request.headers.get("x-api-key")silently returned null — authentication itself was never affected, which is why this presented as "the header works but my resolver cannot see it". Two API Gateway divergences found alongside it: REST (payload 1.0)headersandqueryStringParametersreturned the first duplicate value where AWS returns the last, with all values inmultiValueHeaders; and the HTTP API payload-1.0 branch emitted lowercase comma-joinedheadersbeside Go-canonicalmultiValueHeadersin the same event. -
Web UI — hover, focus and busy states now match the design and, in several places, exist at all: a dozen surfaces used hover classes that were never declared and so did nothing, a
focus-visible::typo meant that ring never compiled, buttons never showed a pointer cursor, and busy buttons were marked disabled so they dimmed and read as unavailable while working. Two keyboard defects went with them — inactive tabs were unreachable (no arrow-key handling behindtabIndex={-1}) and clickable table rows could not be focused. The event stream is legible in light mode, having previously painted itself on a hardcoded near-black panel with text chosen to suit it; its JSON now shares the themed palette the JSON editor already used, and its per-service colours became a defined ramp that keeps two previously-identical pairs apart. EC2 instance state showed contradictory colours between the list and detail views —stoppedred on one and neutral on the other,terminatedthe reverse — because each page defined its own badge. Disabled services now sort to the bottom of their dashboard section rather than sitting between services you can open. -
Web UI — the system map no longer overlaps nodes when a Lambda function has many concurrent instances: Lambda group nodes now cap at four visible instance rows and scroll internally, matching the existing SQS/CloudWatch Logs node pattern. The Raw State Debugger's selection is now URL-backed — reloading or sharing the URL reproduces the exact view, picking a namespace pushes a history entry while clicking through keys replaces it (so back/forward steps through namespaces, not every key ever clicked).
-
Diagnostics — the slow-data-directory startup warning and Metrics & Health advisory no longer tell users already on a named Docker volume to "switch to a named volume": the fsync probe now looks up the data directory's actual filesystem type (
/proc/mounts) and tailors the advice — bind/file-sharing mounts (9p, virtiofs, grpcfuse) still get the named-volume recommendation, while native filesystems (ext4 etc.) get host/VM I/O-pressure guidance instead. The probe also now takes the median of three fsync samples rather than a single boot-time sample, so one transient stall during container startup no longer raises a false alarm;GET /_debug/metricsreports the detectedfsTypeandmountClassalongside the probe result. -
Logging — an invalid
OVERCAST_LOG_LEVELno longer prevents the emulator from starting: it now logs a warning naming the configured value, the effective fallback (info), and the valid values, then continues — previously a typo in this observability setting was a fatal startup error. The SSE event stream's periodic heartbeat log line moved from debug to trace (it fires on an idle server — the log-level policy's litmus test), and heartbeat timestamps now come from the injected clock. -
DynamoDB — GSI
QueryandScannow read from a real per-index ordered structure instead of scanning the entire table on every call (Query on a GSI is now partition-scoped like base-table Query; costs are flat in table size). This also closes a projection-fidelity gap:KEYS_ONLYandINCLUDEGSIs previously returned base-table attributes that real AWS refuses to project — they now return exactly the projected attribute set.TransactWriteItemsnow maintains GSI index entries like every other write path. LSI queries and parallel (TotalSegments) scans intentionally keep the previous behavior. -
Storage — SQLite's WAL auto-checkpoint threshold raised from 1000 to 4000 pages on the persistent/hybrid write path: sustained write bursts previously paid a mid-burst checkpoint that showed up as ~0.9-1.4ms per SQS send at moderate queue depths; measured after the change at ~57-74µs per send (repeatable across independent runs, allocations unchanged, no regression at higher depths). The WAL file may now grow to ~16MB between checkpoints; the background maintenance loop's periodic checkpoint behavior is unchanged.
Release: https://github.com/Neaox/overcast/releases/tag/v0.0.1-alpha.25