Skip to content

Release 0.2.23 - #32

Open
bhati08-duplo wants to merge 21 commits into
mainfrom
release/0.2.23
Open

bhati08-duplo wants to merge 21 commits into
mainfrom
release/0.2.23

Conversation

@bhati08-duplo

Copy link
Copy Markdown

Promotes release/0.2.23 to main for 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.

  • Cut from 14e9b7d, DevKit dev when 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.example pins STUDIO_TAG/AGENT_TAG/UI_TAG/XTERM_TAG to 0.2.23, the final images. They have the same digests as the QA-tested rc.12 images.
  • main merged in (356b520), conflicts resolved keeping both sides:
    • docker-compose.yml: keeps both new services, init-nginx-conf (dev) and the dind sidecar (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 when BUILDER_TAG is unset, calling dev's $RUNTIME (podman support).
    • scripts/build-extension.sh: dev's derived assemblyDir/skills[].folder plus main's sdkDigest stamp.
    • .env.example: 0.2.23 tags; BUILDER_TAG stays 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.23 GitHub release on the merge commit.

🤖 Generated with Claude Code

bennett-elder and others added 19 commits September 25, 2026 16:58
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>
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
…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>
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