Skip to content

fixing/merge-conflict - #1

Open
Pavitra-programmers wants to merge 3960 commits into
Pavitra-programmers:merge-conflictfrom
different-ai:dev
Open

fixing/merge-conflict#1
Pavitra-programmers wants to merge 3960 commits into
Pavitra-programmers:merge-conflictfrom
different-ai:dev

Conversation

@Pavitra-programmers

Copy link
Copy Markdown
Owner

Summary

Why

Issue

  • Closes #

Scope

Out of scope

Testing

Ran

  • ...

Result

  • pass/fail:
  • if fail, exact files/errors:

CI status

  • pass:
  • code-related failures:
  • external/env/auth blockers:

Manual verification

Evidence

  • video/screenshot link, or N/A (docs-only)

Risk

Rollback

reachjalil and others added 30 commits July 21, 2026 10:26
…-error pass-through proof (#2935)

Partially reverts #2927: removes the prompt rule and prompt-content test for the -32001/data.connect_url dialect, retargets the MCP authorization-link e2e at raw provider-error pass-through, and keeps the shared mock support intact.
* fix(app): keep sign-in URL visible

* test(evals): prove visible sign-in URL
)

* feat(desktop): debug-only nuke & fresh start with full state wipe

* test(evals): fraimz flow for debug nuke & fresh start on Windows

* test(evals): split Windows nuke proof commands below cmd limits

* test(evals): use encoded PowerShell for Windows nuke witnesses

* test(evals): stabilize renderer auth fixture after reload

* fix(desktop): fail closed when bootstrap cannot be sanitized during nuke

* test(evals): assert clean default preferences after nuke

* test(evals): tolerate bounded Daytona exec jitter in Windows nuke proof

* test(evals): flatten Windows PowerShell nuke probes

* test(evals): distinguish wiped state from clean runtime regeneration

* fix(desktop): retain pending nuke cleanup until locked paths are gone

* fix(desktop): finish locked nuke cleanup out of process before relaunch

* fix(desktop): wait for Chromium debug port release before nuke relaunch

* fix(desktop): reprobe debug port after out-of-process nuke relaunch

* test(evals): parse JSON before trailing PowerShell CLIXML

* test(evals): use out-of-band Windows boot for locked nuke retry

* test(evals): wait for cold Windows lock helper startup
Keep model and thinking controls available during ordinary assistant generation while disabling them for steered runs.
* fix(app): hide build identifier from sidebar

* test(evals): remove obsolete sidebar identifier flow
* fix(app): keep session spinner clear of title

* test(evals): prove session spinner spacing
* feat(desktop): make bootstrap preservation optional

* test(evals): prove bootstrap nuke toggle
* feat(marketplaces): safely delete custom marketplaces

* test(evals): prove custom marketplace deletion

* feat(marketplaces): move management into actions menu

* fix(marketplaces): hide built-in management actions

* fix(marketplaces): hard-delete custom marketplace records
…anced diagnostics (#2975)

* feat(mcp): add cloud MCP doctor — probe trace, engine refresh, advanced diagnostics

The openwork-cloud meta-MCP fails opaquely today: OpenCode stores only
Error.message for a failed remote connect (a TLS/proxy failure collapses to
the literal "fetch failed"), never retries on its own, and the desktop card
reduces everything to "Couldn't apply Cloud access to this workspace".

Server:
- Direct endpoint probe now records a per-step trace (initialize,
  initialized notice, tools/list) with HTTP status, latency, endpoint server
  info, and — on transport errors — the full cause chain (code/errno/syscall)
  that the engine discards.
- New POST /workspace/:id/mcp/openwork-cloud/engine-refresh: disconnects the
  engine's MCP client, re-registers from the persisted desired config
  (an unconditional fresh connect on the engine side), and returns ordered
  refresh steps plus probed health.
- Health now carries engineInspection — the engine's full MCP server map with
  per-server states and raw error strings — so support can tell "everything
  failed" (host network path) from "only openwork-cloud failed" (endpoint or
  token) from "entry lost after an engine restart".
- Health gains durationMs; reconcilePersistedOpenworkCloudMcp accepts
  providerModel.

App:
- Test now requests probe=1, verifying the Cloud endpoint directly from the
  OpenWork server instead of only reading the engine's cached state; the
  Advanced settings page refresh does the same.
- The Agent access card gains a collapsed-by-default Advanced diagnostics
  section: failure code/stage/retryability, the raw engine error, delivery
  revisions, probe step trace, engine MCP server map, token expiry, versions,
  a Refresh engine connection action, and a redacted copyable support bundle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(mcp): keep behavior outside diagnostics unchanged under richer errors

Two hardening guards from a behavior-impact audit:

- inferFailedStatus: certificate/TLS transport errors (which can contain
  "expired", "auth"(ority), or "revoked" wording — especially once engines
  preserve error cause chains) are never classified as token or session
  problems; they stay generic connection failures. Prevents richer engine
  error strings from changing the repair verdict.
- engine-refresh route: an empty body stays allowed, but malformed JSON is
  now a hard 400 instead of being silently treated as empty.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* chore(app): remove dead primitives

* fix(evals): wait for persisted assistant response

* fix(evals): assert current extensions labels

* fix(evals): use canonical reopen proof
* feat(diagnostics): add Connect debug proxy

* chore(diagnostics): fix publication formatting

* fix(diagnostics): preserve proxy during desktop auth

* fix(diagnostics): proxy Den browser auth routes
* test(den): cover MCP OAuth refresh lifecycle

* fix(den): tolerate concurrent MCP token refresh (#2963)
… fork, mismatch guard, verified handoff) (#2973)

* feat(installer): point paste screen back to the install page + expired-link message

* feat(den-api): add desktop handoff status

* feat(den-web): confirm desktop handoff connection

* feat(desktop): read bootstrap synchronously on launch

* feat(app): add first-run organization join option

* feat(app): guard managed server sign-in links

* feat(evals): first-connection voiceover + scaffold

* fix(den-api): stamp configured-dir installer zips + candidate filenames; den-web: mint install links on active origen

* feat(evals): first-connection flow implementation + den-stack hardening

* fix(evals): handle email-first den sign-in

* fix(evals): avoid empty den auth submit

* fix(evals): capture bare installer fallback state

* fix(evals): expire throwaway install link

* fix(evals): assert current desktop signin server

* fix(evals): reset installer dry-run bootstrap

* fix(evals): wait for desktop server connection label

* fix(evals): reset first-connection onboarding state

* fix(evals): read visible desktop signin link

* fix(evals): reload desktop welcome reset

* fix(evals): clean invitee browser tabs

* fix(evals): keep invitee browser alive

* fix(den-api): stamp generic Windows installer downloads

* test(evals): add first-connection Windows evidence

* test(evals): note server sandbox id
* refactor(app): consolidate markdown rendering

* fix(evals): validate visible highlight evidence

* fix(evals): reset markdown search state
* feat(evals): typed runner core + automation/demo mode split

- pnpm evals = automation mode: no voiceover/narration policy anywhere
- pnpm fraimz = demo mode: unchanged behavior (drift check, narrated frames)
- runner converted to TypeScript on Node 24 native type-stripping (no build
  step, no new runtime deps); run.mjs stays as a thin bootstrap
- typed flow contract: defineFlow + FlowContext (evals/runner/flow.ts);
  new flows are *.flow.ts, legacy *.flow.mjs still load via compat shims
- scaffold emits typed .flow.ts stubs; plain stub without a script in
  automation mode, approved script still required in demo mode
- OPENWORK_EVAL_VOICEOVERS_DIR override for fixture isolation
- tsc gate (pnpm evals:typecheck) + runner unit tests (pnpm evals:test)
- nightly workflow pinned to pnpm fraimz --all to keep drift coverage

* feat(evals): typed-automation-dx internal demo flow

Narrated internal demo (approved script: evals/voiceovers/typed-automation-dx.md)
proving the DX end to end: mode split wiring, drift decoupling, scriptless typed
scaffold, tsc contract gate, legacy compatibility, and demo-path default.

* fix(helm): point den-api entrypoint guard at den-stack.ts

The chart test cross-references the eval den-stack to keep the den-api
entrypoint consistent; den-stack.mjs became den-stack.ts in this branch.
* refactor(app): centralize workspace server clients

* fix(evals): parse workspace session route safely
reachjalil and others added 30 commits July 27, 2026 14:51
* feat(den-web): offer OpenWork Cloud from install page

* feat(desktop): add OpenWork Cloud installer distribution

* fix(install): enforce desktop distribution doors

* fix(den-web): keep Cloud install handoff simple

* fix(den-web): make Cloud download the primary action
…3184)

* feat(settings): add Extensions inventory primitives and i18n

Add SettingsGroupHeader, SettingsFactRow, ExtensionRequirementList,
resolveExtensionInventoryGroup, and updated Extensions copy.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(settings): retire Connect tab into Extensions and Debug

Redirect /settings/connect to Extensions, move Agent access into Debug,
and keep Connect row helpers for inventory grouping.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(extensions): group inventory by readiness and unify detail state

Render Extensions cards under Needs sign-in / admin / Ready / Available /
Disabled headers, relabel MCP as App, and collapse detail targets into one
state (full /settings/extensions/:id page still TODO).

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(composer): nest apps under Extensions; update Connect guidance

Drop the separate MCPs tools rail section and point agent knowledge at
Settings > Extensions (and Debug for repair).

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(server): point runtime steering at Extensions inventory

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(extensions): open extension detail as a dedicated settings route

Route `/settings/extensions/:id` to a page shell while keeping mcp/skills/plugins
as section aliases, so deep links and back navigation stay shareable.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: GitHub Action <action@github.com>
* fix(desktop): isolate explicit bootstrap activation

* fix(desktop): prioritize enterprise activation policy

* fix(app): gate sign-in behind enterprise activation

* fix(desktop): preserve branded enterprise activation links
#3184 left ManageInDenButton referencing openDesktopUrl, t, and ArrowUpRight
without imports. The button is dead code today, but its i18n key exists, so
keep the teammate's in-progress path rather than deleting it.

The Extensions inventory initialFilter was also inferred as a bare string
before being passed to mcpView. Type it as ExtensionsInventoryFilter so dev's
@openwork/app typecheck stops failing for everyone.
* fix(composer): collapse pastes only on overflow

* fix(composer): render pasted text normally

* fix(composer): support paste chips before sessions
* fix(app): render markdown tables in the artifact editor

Markdown artifacts open in the CodeMirror merged view, which was configured
with the CommonMark base grammar, so GFM tables were never parsed and the
live preview had no table case. A document full of tables showed up as raw
pipes, divider row included.

Parse with the GFM base and replace each table with the same sanitized HTML
the rest of the app renders markdown with. Selecting into a table hands the
markdown source back, so the document stays editable. Block decorations may
not come from a view plugin, hence the separate state field.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(app): keep rendered tables reachable by click and arrow keys

Clicking a rendered table put the cursor on its first line whatever row was
clicked, and vertical cursor motion stepped over the whole block because a
replaced range has no text positions inside it, so a keyboard user could not
get into a table at all.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
* chore: remove the openwork-orchestrator

The orchestrator was the last thing standing between OpenWork and a single
server binary. Cloud already ran without it; this removes it everywhere else
and deletes the package.

Render workers are now purely openwork-server: the build installs the
published npm package instead of the orchestrator, the start command drops
every orchestrator-only flag (--remote-access becomes --host 0.0.0.0,
--opencode-source/--opencode-bin become OPENWORK_MANAGE_OPENCODE and
OPENWORK_OPENCODE_BIN, --allow-external and --connect-host simply go), and it
resolves the extension plugins from the installed package - failing loudly if
they are absent rather than booting into the silent
extensions_plugin_missing state Cloud just hit. install-opencode.mjs reads
the pinned OpenCode version from the repo's own constants.json instead of
from the globally installed orchestrator.

The desktop stops shipping it. It was compiling, signing, notarizing and
shipping eight orchestrator binaries per release that nothing ever ran:
engineStart has always hardcoded the direct runtime, and both
startOrchestratorRuntime and startDirectRuntime were defined and never
called. The dead runtime paths, the detached-start IPC and its types, and the
sidecar packaging entries are gone; boot now calls engineStart directly
instead of a vestigial orchestratorWorkspaceActivate that only delegated to
it.

The single-container and microsandbox images run openwork-server directly,
with the plugins shipped and OPENWORK_EXTENSIONS_PLUGIN_DIR set. Their data
directory keeps its historical name on purpose - existing deployments have
volumes mounted there and renaming it would silently orphan their state. That
is a directory name only; the CLI is gone.

The release pipeline loses the sidecar job and the npm publish, and
verify-tag, review and bump-version no longer read a package.json that no
longer exists - they would have thrown on every release.

Legacy cleanup is deliberately preserved: users still have
~/.openwork/openwork-orchestrator on disk, so nuke keeps wiping it and the
tests keep asserting that.

Verified: apps/orchestrator deleted and the lockfile updated; app, server,
desktop-electron, den-api and den-web typechecks clean; 53 desktop electron
tests, 20 den-api cloud tests, 20 server db/env tests and the stats tests
pass; i18n audit passes across all locales; release review and verify-tag run
clean without the folder; every changed YAML parses. The server suite is
1083 pass / 7 fail, byte-identical to the pre-existing baseline on clean dev
(reload watcher/event timing plus one suite-order plugin test). The landing
prebuild parity check also fails identically on clean dev - unrelated.

* test(evals): make the cloud e2e sign-in frame state-independent

Frame 2 asserted the org-chooser screen, which only appears when a workspace
or server is already configured in the browser profile. It passed on the
dirty profiles I had been reusing and failed on a clean one - the app
legitimately lands on the first-run welcome screen instead.

It now proves what the frame actually claims: Den accepts the signed-in
admin session (node-side /v1/me, asserting the email matches), the browser
carries it, and the forced sign-in gate is no longer blocking. The wait is a
positive one for any settled post-gate surface, because a negative wait
passes on the empty DOM right after reload and the capture then lands on the
"checking" flash where app-root re-renders the gate.

Two runner behaviors worth recording: ctx.eval does not await promises, so an
async IIFE serializes to {} - probes belong node-side; and the screenshot
validator sees a later moment than the assertions, so transient states must
be waited out, not asserted around.

* fix(scripts): let the Daytona snapshot build run on arm64

The snapshot image is always linux/amd64 because that is what Daytona runs,
but the Dockerfile's runtime asserts execute the installed binaries. On an
arm64 machine those x86_64 binaries run under emulation and die with
"Illegal instruction (core dumped)", so the script could never build a
snapshot on Apple Silicon - it failed at the final assert stage every time.

Default RUNTIME_ASSERTS to 0 when the host is not x86_64, which is exactly
the cross-build path the Dockerfile already documents as "binaries must be
verified on target hardware". x86_64 hosts and CI keep asserting as before,
and the chosen value is echoed so a cross-build is obvious in the log.
* feat(extensions): name apps, connections, and MCPs consistently

Extensions rows now say what they are: apps run on this device, connections
are accounts, MCP servers are servers configured here. Each is filterable,
and the browse catalog of things you never installed is gone -- the page
lists what you have plus built-ins you can turn on. Manual MCP setup moved
into Advanced settings.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(extensions): drop Google Workspace as a local extension

Google Workspace now reaches OpenWork through an OpenWork Cloud org
connection, so the desktop no longer ships it as a built-in extension
with its own local OAuth panel. Every remaining built-in runs on this
device, which lets the taxonomy drop the manifest surface flag and the
runtime connection registry that only Google Workspace used.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
…iled failure attribution (#3199)

Extend the Agent Context cloud catalog probe into a full independent
runtime MCP verification of the managed openwork-cloud endpoint:

- Name the runtime transport explicitly (runtimeDiagnosticFetch +
  runtimeDiagnosticTransportInfo in server-fetch.ts) so reports state
  whether Node/undici (Electron main or standalone Node), Bun's fetch,
  or a test seam performed the probe, and harden the bare-fetch guard so
  reference fallbacks such as `?? fetch` can no longer bypass it.
- Decouple probe eligibility from cached OpenCode registration state and
  from agent tool policy; both remain reported dimensions and become
  comparison inputs for a new differential verdict instead of gates.
- Run the complete bounded MCP handshake: initialize (with protocol
  version validation), notifications/initialized, tools/list, and a
  bounded best-effort DELETE session cleanup that never converts a
  successful availability check into a failure. No tool is ever called.
- Attribute failures precisely: closed stage enum (dns/connect/tls/
  proxy/initialize_*/initialized_notification/tools_list_*/
  catalog_validation/session_cleanup), closed sanitized network-cause
  codes, split HTTP classes (401/403/404/429/502-504/redirects), split
  protocol classes (utf8/json/envelope/request-id/protocol-version/
  session-header/catalog/pagination), and deterministic retryability
  derived only from closed code sets.
- Accept forward-compatible catalogs: extra provider tools no longer
  fail validation, but only the allowlisted expected tool IDs and
  aggregate counts are exported; both required tools must be present.
- Add a cloud-endpoint-differential check distinguishing endpoint
  availability from engine availability (runtime_and_engine_connected,
  runtime_connected_engine_failed, runtime_failed_engine_connected,
  runtime_and_engine_failed, runtime_probe_not_performed,
  engine_evidence_stale_or_unavailable) with engine evidence source and
  age surfaced.
- Keep the trust boundary: only built-in Cloud origins, exact
  administrator-configured origins, and loopback may receive the
  credentialed probe; untrusted_endpoint is reported as probe-not-
  performed trust configuration, never as a network or MCP failure.
  Boolean-only proxy/extra-CA posture and a strictly validated
  x-request-id reference are the only environment-derived exports.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…tance (#3191)

First slice of ui.openworklabs.com. den-gateway serves the OpenWork web
build and proxies each signed-in user to their own Cloud instance,
injecting that instance's credentials server-side. The browser never
receives an instance token or a preview URL, and never learns which
compute vendor is behind it.

The security boundary is the point: the gateway holds no Daytona key,
never imports the SDK, and has no database access. den-api remains the
only thing that talks to Daytona. The gateway also cannot assert identity
on its own - it acts strictly on behalf of the caller's Den session, so
den-api's per-process internal-principal secret stays untouched.

den-api gains GET /v1/cloud/gateway/resolve: the caller's own session plus
a shared gateway secret (timing-safe, and the route 404s when the secret
env is unset, so it does not exist on deployments without a gateway). It
returns the instance URL and collaborator token only when ready, never the
host token, and reuses the existing per-user state machine rather than
forking it.

Routing is the subtle part. Every allowlisted entry matches as a namespace,
because /files/sessions/*, /workspaces/local, /workspaces/:id/activate,
/env/keys and /approvals/:id would otherwise fall through and answer an API
caller with HTML. And /workspace/ is genuinely ambiguous - openwork-server
owns API routes there while the BrowserRouter SPA owns reloadable
session/settings deep links - so document navigations serve index.html
while everything else proxies. /opencode/ and /w/ are always API, since
openwork-server claims all of /w/.

Streaming correctness is deliberate: the SPA holds two permanently-open SSE
streams, so bodies are piped rather than buffered, content-encoding and
transfer-encoding are stripped (undici already decoded), no idle timeout is
imposed, and upstream caching passes through. Static serving mirrors
openwork-server: SPA history fallback, immutable /assets caching, and a hard
404 for a missing hashed asset so a stale index surfaces as a 404 instead of
HTML parsed as JavaScript. Gateway health lives at /__gw/health because
/health belongs to the instance.

Lands the approved voice-over and scaffolded flow for the den-gateway demo.

Slice 1 only: apps/app is not wired to it yet and no deployment config is
included.

Verified: den-gateway builds, 10 gateway tests pass (static, SPA fallback,
asset 404, traversal, injection, resolve cache, non-ready, SSE
non-buffering, gzip, and every routing case above); 24 den-api cloud tests
pass including the new resolve gating.
…ine-evidence staleness (#3200)

* fix(diagnostics): probe activated on-prem Den origins and correct engine-evidence staleness

Follow-up to #3199, from a real enterprise diagnostics report where the
runtime probe could not run at all.

Trust the activated enterprise control plane. An on-prem deployment's
managed openwork-cloud entry points at the customer's own Den origin, so
the probe reported untrusted_endpoint and sent nothing — leaving exactly
the deployments that most need differential diagnosis with no evidence
beyond OpenCode's opaque "failed". The desktop writes
enterpriseActivation only after a signed activation claim verifies, so
that record is administrator-provisioned configuration rather than a
renderer- or request-supplied URL. The server now reads it (bounded,
read-only, local workspaces only) and admits its exact origin to the
diagnostics allowlist. Arbitrary URLs, non-https origins, and
credential-, query-, or fragment-bearing values are still rejected, and
a missing or malformed record fails closed.

Report trust provenance instead of the origin. trustSource
(builtin-cloud | loopback | administrator-env | enterprise-activation |
untrusted | not-evaluated) and enterpriseActivationPresent let an
administrator tell "this install is not activated" apart from "it is
activated, but against a different origin than the configured Cloud MCP"
— a real misconfiguration that previously looked identical — without the
report ever carrying a hostname.

Correct the differential staleness rule. Treating any engine record
older than 60s as stale made every healthy steady-state run report
engine_evidence_stale_or_unavailable, because a connected registration
is the engine's standing state and ages naturally between syncs. Only a
failure record the reachable engine could already have refreshed is
downgraded, mirroring mcp_registration_stale_failure; an aged failure on
an unreachable engine keeps implicating the engine.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(diagnostics): assert the probe only ever reaches the configured Den endpoint

An on-prem operator's probe must reach their own Den deployment, never
OpenWork-hosted Cloud. The built-in origins are a membership allowlist
consulted with .has() and are never a destination or fallback, but that
invariant was only enforced by inspection. Pin every request URL of the
handshake and the session cleanup to the exact configured endpoint, and
assert no OpenWork-hosted origin is contacted, at both the probe and
analyzer levels.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…able image (#3202)

* feat(den-gateway): run the app behind the gateway on one origin

Wires apps/app to den-gateway so browser traffic is single-origin and the
browser holds no instance credential.

- The gateway proxies /api/den/* to den-api, forwarding the caller's Den
  bearer unchanged (Den is the intended audience) and never attaching the
  gateway key, which is only for the resolve call. Cookies are not
  forwarded; the SPA is bearer-authenticated. Same streaming rules as the
  instance proxy.
- The gateway injects a token-free marker into index.html so the app can
  tell it is behind a gateway.
- In gateway mode the app resolves the OpenWork server base and the Den
  base from window.location.origin, sends its Den session token as the
  bearer, and ignores window.__OPENWORK_BOOTSTRAP__ entirely, so no
  instance token is ever written to storage.

Because both the app and Den are same-origin behind the gateway, this is
what makes the three CORS patches from this week unnecessary rather than
load-bearing.

Desktop and the existing direct-instance path are untouched when the
gateway marker is absent - asserted by tests covering bootstrap-token
hydration, stored settings precedence, and desktop server info.

Verified: gateway builds; 13 gateway tests and 6 app gateway-runtime tests
pass; build:web succeeds. apps/app tsc has 5 pre-existing errors on dev
(agent-access-card.tsx, extensions-view.tsx) confirmed against a clean
base; none added here.

* fix(den-gateway): allow gateway sign-in returns

* fix(den-gateway): suppress instance web token

* feat(den-gateway): package gateway image and publish in CI

Bake the OpenWork web build into the gateway image so the app and Den share
one origin, and register the image in the EE publish matrix. The gateway's
own liveness is /__gw/health because /health proxies to the user instance.

* fix(ci): build newly added EE images instead of skipping them

The build step's condition was an allowlist of image names, so a new matrix
entry silently skipped the build and then failed the smoke step with a
confusing registry 'denied' error. State it as an exclusion instead.
…nstaller app (#3203)

* fix(desktop): load system CAs from OS trust stores for engine TLS trust

resolveSystemCaEnv had one source, tls.getCACertificates("system"), which
returns 0 certificates on macOS and misses intermediates outside the ROOT
store on Windows. Behind a corporate CA the Chromium surfaces worked while
OpenCode (Bun) failed every TLS connection to the org endpoint with
'unable to verify the first certificate'.

- port the additive loader to apps/desktop/electron/system-ca.mjs:
  Windows LocalMachine/CurrentUser Root+CA stores via PowerShell, macOS
  admin keychains via security find-certificate, merged and deduped into
  system-ca-bundle.pem for NODE_EXTRA_CA_CERTS
- extend the Electron main process default CA set with the same additions
  (best-effort tls.setDefaultCACertificates) so the embedded OpenWork
  server's own probes trust the corporate CA; env mutation after boot
  never reached it
- operator-set NODE_EXTRA_CA_CERTS keeps its skip-and-win semantics

* chore: remove the obsolete standalone installer app

The generic installer (apps/installer) is replaced by the release
pipeline shipping desktop assets directly. Remove the app, its build and
release workflows, eval flows, version bumping, outbound-access scan
entry, and the OpenWork-Installer-* asset plumbing in den-api install
links, den-web install screens, and the landing release-asset filter.
Configured install-link artifacts now resolve by the standard versioned
desktop asset filename. packages/install-config and packages/paths stay
(install links are a Den feature).

* chore: drop unrelated whitespace and grep-dodging edits from the merge
…ll dead-end (#3204)

Stable/enterprise users hit "Couldn't check for updates" with the raw
reason update-not-downloaded when clicking Install & restart: the main
process cleared its in-memory updateDownloaded flag on ANY updater error
event and on transient failed checks, while the renderer's "Ready to
install" state never learned about the reset.

- main: only a successful check proving no update (or a real download
  failure) invalidates a staged download; transient errors no longer do
- renderer: an install attempt that hits the stale flag now re-runs the
  policy-aware manual check and lands back on a working download flow
  instead of dead-ending on a raw internal reason
- view: action-specific error headlines (install/download vs check)
- tests: fake-updater lifecycle regression tests via loadAutoUpdater seam
- evals: update-install-self-heal fraimz flow + voiceover
… transport evidence (#3201)

Self-hosted Den deployments behind corporate TLS failed openwork-cloud MCP
registration for three weeks with zero captured cause: the engine's error
string was discarded at parse time, the credentialed catalog probe fails
closed for self-hosted origins, and mcps[] hid the real endpoint.

- persist OpenCode's registration error (sanitized, bounded) through the
  registration record into engine-mcp-sync failedRegistrations, with a
  classified transportCause (tls_incomplete_chain, tls_untrusted_ca, ...)
- scrub URL/path segments to [url]/[path] placeholders instead of
  whole-string redaction so endpoint-bearing TLS errors survive sanitization
- new credential-free cloud-endpoint-transport check: bare TLS handshake
  captures the exact verify error code, served chain length/subjects, and
  local trust evidence (system CA count, NODE_EXTRA_CA_CERTS state)
- report real origin + path for managed openwork-cloud MCP entries
- keep the credentialed-probe trust gating and report-safety claims intact
…3206)

* fix(diagnostics): omit SNI servername for IP-literal cloud endpoints

tls.connect with servername set to an IP literal throws
ERR_INVALID_ARG_VALUE on Node (SNI forbids IP addresses), so the
transport probe misreported configuration errors as verify failures for
IP endpoints and broke three tests on CI runtimes that enforce the rule.
Strip IPv6 brackets for the host and set servername only for DNS names.

* fix(desktop): default the updater loader so the IPC contract typecheck passes

registerUpdaterIpc gained a required loadAutoUpdater seam in #3204 but
main.mjs and the test fixtures never passed it, breaking the Electron
typecheck on dev. Declare the electron-updater import as the parameter
default, which both fixes the inferred contract and simplifies
ensureAutoUpdater.
…URL without an org (#3207)

* fix(app): scope gateway Den API origin

* fix(den-api): approve gateway handoff without active org
…ing sign-in again (#3209)

* fix(app): reflect gateway session after web handoff

* fix(app): avoid blank welcome when den unavailable
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants