Commit Graph
3 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5 40f2bb933d fix(flowise): scope the shim path to its layer instead of a build arg
f58ff5522 gave the socket-timeout shim a single point of truth by way of a
defaulted ARG. test_arg_without_default.py forbids that tree-wide:

    roles/web-app-flowise/files/Dockerfile:7: ARG FLOWISE_SOCKET_TIMEOUT_SHIM carries a default

The rule's reasoning does not fit this value at all: "A defaulted ARG answers a
question the caller failed to answer. The build then succeeds against a base
image, version or path nobody chose." An ARG is a contract with the caller, and
nobody needs to answer where a temp file lives that is written on line 21 and
deleted on line 25 of the same layer.

f45df04bf1 shows the house pattern for the case where the value IS a caller
decision: it dropped PY_BASE's default from bridgy-fed and had compose.yml.j2
supply it. Doing that here would invent a build contract for a scratch file.

A shell variable keeps the single point of truth and narrows the scope on top of
it -- the name was visible across the whole build context as an ARG, and now
lives only inside this RUN. Same path, same three references, same build.

Suppression was available and not used: a nocheck marker would have kept the
wrong mechanism and hidden the reason it was wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-01 00:20:29 +02:00
kevinveenbirkenbachandClaude Opus 5 f58ff55226 fix(flowise): survive a stalled prebuilt-binary download
GitLab#1 of run 33414875521 died in the flowise image build. The obvious line is
not the cause:

    npm error command sh -c prebuild-install -r napi || node-gyp rebuild
    npm error prebuild-install warn install Request timed out
    ...
    npm error gyp ERR! stack Error: not found: make

`not found: make` is the third domino. Counting the whole job settles it:
`Request timed out` 38, sqlite3 failures 6, `not found: make` 6 -- and sharp
failures 16, of 22 build attempts total. sharp emits no gyp output at all; its
fallback dies at `can-compile` because the image ships no libvips. A toolchain
would have touched 6 of 22 and left the dominant mode alone.

What actually aborts: node >=19 puts a 5s socket-inactivity timeout on
https.globalAgent (v24.19.0 lib/internal/http.js:263-268), while sharp and
prebuild-install fetch their prebuilt binaries through simple-get, which sets no
timeout of its own and never retries. Any 5s gap in the byte stream of the ~8 MB
libvips tarball drops the whole RUN layer.

The trigger was environmental, and it is worth being explicit that it was: the
same run, the same commit and the same base-image digest built flowise green
twice in another job, overlapping these failures. MTU is 1500 in both jobs, there
is no proxy configured, and svc-net-tor redirects only 10.240.0.0/12, so
github.com never enters Tor. The apt layer of the failing build itself fetched at
6178 kB/s and npm resolved all 3196 packages in the same 157s as the green one.

The fragility is ours. Eleven lines above, the apt layer already carries
-o Acquire::Retries=3; the npm layer had nothing. That asymmetry is what this
closes.

NODE_OPTIONS is attached to the install command alone rather than exported for
the layer: npm init and npm pkg set reach no network, and npm install is what
spawns the lifecycle scripts that download. --require is kAllowedInEnvvar on this
node (src/node_options.cc:1124-1127). No ENV, so the runtime image and flowise's
own HTTP behaviour are untouched. 60s is 12x headroom over a real stall while a
genuinely dead socket still fails inside a minute.

Not proven: that 60s clears this particular stall. The stall duration is nowhere
in the log, and per 850b795a51 a local quality gate cannot answer a
network-dependent question at all. Only a CI build closes that.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-01 00:08:45 +02:00
kevinveenbirkenbach 23ce4355e6 feat(web-app-flowise): build our own image and wire it as an MCP client
The published image lies about its version: flowiseai/flowise 3.1.3, 3.1.4 and
latest all ship package 3.1.2, measured in the running container rather than
inferred from the tag. An unpinned global npm install layer is reused between
releases. We build from the declared version instead.

The build installs locally rather than globally because flowise declares node
^24 from 3.1.3 on while resolving better-sqlite3 to 9.6.0, whose binding.gyp
pins -std=c++17 against node 24 headers demanding C++20. That version cannot
build there at all, and an npm override is only honoured for a local install.

Three upstream behaviours were read at the pinned source before being worked
around: cookie authentication is routed only behind an x-request-from header,
the key controller rejects an empty permissions list, and key creation answers
with the whole key list instead of the new key.

The identity password is written straight into the user row because flowise
accepts a password at registration only, and registration works once; a
redeploy carrying a rotated credential otherwise meets an account whose hash
still encodes the previous one.

Server registration refuses anything that does not speak SSE. This flowise
authorizes with an SSE toolkit, so registering another transport would claim a
connection that cannot be made.
2026-08-06 20:59:58 +02:00