Repository navigation
Release 0.2.23 - #32
Open
bhati08-duplo wants to merge 21 commits into
Open
bhati08-duplo wants to merge 21 commits into
bhati08-duplo wants to merge 21 commits into
Conversation
The UI image serves on 8080 and its baked-in healthcheck probes http://127.0.0.1:8080/. devkit mounts its own default.conf over the image's server block, and that conf listened on 80 — so nginx bound 80, the SPA served correctly, and the healthcheck got connection refused. The container has sat permanently (unhealthy) for every UI tag published since the image moved to 8080, including the UI_TAG in .env.example. Nothing gates on duplo-ui's health, so serving was never affected. The cost is a status that misreports, and a conf mount that masks the port the image actually uses — so exercising a UI tag in devkit says nothing about how that image behaves where the port matters. - nginx/default.conf: listen 8080 - docker-compose.yml: map ${UI_PORT:-4200} to 8080 localhost:${UI_PORT} is unchanged from the user's side. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ng Docker's The UI proxies API prefixes to the studio so the browser stays same-origin, and since 63e6d2f that proxy_pass goes through a variable to force per-request DNS resolution — which requires an explicit `resolver`. That resolver was pinned to 127.0.0.11, Docker's embedded DNS, which does not exist under podman: its aardvark-dns sits on the network gateway (10.89.0.x, varying by network). The failure mode is the worst shape available. nginx starts, the SPA is served normally, and every proxied API call dies with no response at all — including POST /api/Account/PasswordLogin, so the login page renders and simply does nothing. The only clue is "recv() failed (111: Connection refused) while resolving, resolver: 127.0.0.11:53" buried in the UI container's log. Rather than branching on the runtime, ask the network. Any container attached to the project network is handed the correct nameserver by the runtime itself, so a busybox init service reads its own /etc/resolv.conf, substitutes the value into nginx/default.conf, and writes the result to a volume that duplo-ui mounts. There is no docker-vs-podman case to keep in sync, and it stays correct for any runtime added later. It cannot be done inside the UI image: its entrypoint is `nginx` directly — no /docker-entrypoint.d/, no /etc/nginx/templates — and it runs as nonroot 65532, so the usual envsubst-on-a-template trick is unavailable. nginx has never read /etc/resolv.conf for its own `resolver` directive, so substitution has to happen before nginx starts. The init-container shape mirrors init-perms, already in this file. Verified on both runtimes, same image and same compose file: podman nginx resolver = 10.89.0.1 SPA 200, /v1/... 401, login 401 docker nginx resolver = 127.0.0.11 SPA 200, /v1/... 401, login 401 401 is the pass: nginx resolved the upstream and the studio answered with an auth challenge. Before the fix the same calls returned 000 — nginx never reached it. Zero resolver errors in the UI log on either runtime. tests/test-ui-nginx.sh covers it statically, so it runs on any machine with no runtime installed: the conf must not pin a runtime-specific address, the init service must read /etc/resolv.conf rather than a literal, duplo-ui must wait for it via service_completed_successfully, and shell variables in the init command must be written $$ — compose interpolates $VAR in `command:` before the shell sees it, and an interpolated-away variable yields an empty resolver and an nginx that will not load its config at all. Note the volume replaces the whole /etc/nginx/conf.d directory; the image ships only default.conf there, and the test guards that assumption. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Derive the manifest's versioned paths from id and version at build time
fix(ui): listen on 8080 to match the UI image's own port
The license server now accepts consumer domains (gmail, icloud, yahoo) alongside business addresses. Only privacy-relay and known-spam/disposable domains are rejected, so the "work address only / personal domains are not accepted" wording is no longer accurate. - run.sh: retry prompt is now `Email address:` instead of `Work email:`, and the non-interactive/give-up errors describe the real rule - README, quickstart, install, prerequisites, configuration, faq, cli-reference, troubleshooting, hackday guide: same softening The server's own rejection message is still echoed verbatim first; the devkit wording is only the follow-on hint. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
docs: soften email requirement messaging
fix(ui): discover the nginx resolver at run time instead of hard-coding Docker's
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
#22) Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C8ZDrXkBjXRL2ekNfsV6Up
Add a build gate that verifies Agent-mode extensions (those with non-empty skillMappings in manifest.json) render the <app-ai-disclosure> component on their forms, per ISO 42001 requirements. - scripts/_ai_disclosure_gate.sh: new gate helper, sourced by tests and build - tests/test-ai-disclosure-gate.sh: 7 test cases (Agent-mode with/without tag, Worker extensions, malformed JSON, error messaging) - scripts/build-extension.sh: wire the gate after naming validation Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C8ZDrXkBjXRL2ekNfsV6Up
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C8ZDrXkBjXRL2ekNfsV6Up
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C8ZDrXkBjXRL2ekNfsV6Up
…clusion, docs Warn (not fail) for Agent-mode extensions on ng-common-lib < 0.4.0, ignore the copied wizard-stepper tag, add gate tests, and document the check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C8ZDrXkBjXRL2ekNfsV6Up
Backfilled by hand: both the 0.2.23 dev and release runs skipped DevKit (GH013), so no release branch was cut. Cut from dev at the 0.2.23 release cut (14e9b7d). The four tags point at the final 0.2.23 images, with the same digests as the QA-tested rc.12 images. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- .env.example: image tags keep the release's 0.2.23. BUILDER_TAG stays commented like main (the pinned builder), with dev's runtime-neutral `<runtime> volume` wording. - docker-compose.yml: keeps both new services, dev's init-nginx-conf and main's dind sidecar (#30). The builder image takes main's pinned-digest default, still one level of interpolation for podman-compose. - scripts/_builder.sh: main's "pinned image when BUILDER_TAG is unset", calling dev's "$RUNTIME" instead of docker (podman support). - scripts/build-extension.sh: dev's derived backend.assemblyDir/skills[].folder plus main's sdkDigest stamp. Checked: bash -n, compose config (all 9 services), and the manifest jq on a sample. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aboutte
approved these changes
Oct 13, 2026
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.
Promotes
release/0.2.23tomainfor helpdesk production release 0.2.23. Backfilled by hand this once: both the 0.2.23 dev and release runs skipped DevKit (GH013), so the pipeline never cut this branch.14e9b7d, DevKitdevwhen the 0.2.23 release run started (2026-10-07). It carries the dev work up to then, e.g. the DUPLOAI-3817 AI disclosure and the release-action docs..env.examplepinsSTUDIO_TAG/AGENT_TAG/UI_TAG/XTERM_TAGto0.2.23, the final images. They have the same digests as the QA-tested rc.12 images.mainmerged in (356b520), conflicts resolved keeping both sides:docker-compose.yml: keeps both new services,init-nginx-conf(dev) and thedindsidecar (main feat(compose): add docker-in-docker daemon for the agent (main) #30). The builder image takes main's pinned-digest default, still one level of interpolation for podman-compose.scripts/_builder.sh: main's pinned image whenBUILDER_TAGis unset, calling dev's$RUNTIME(podman support).scripts/build-extension.sh: dev's derivedassemblyDir/skills[].folderplus main'ssdkDigeststamp..env.example: 0.2.23 tags;BUILDER_TAGstays commented like main.Checked:
bash -n, compose config (all 9 services), and the manifest jq. A full build and stack run have not been done.The Prod Pipeline merges this after release approval and publishes the
devkit-0.2.23GitHub release on the merge commit.🤖 Generated with Claude Code