The install path a stranger reads, and a CI probe that never probed #246

Merged
bvandeusen merged 2 commits from dev into main 2026-09-02 11:25:28 -04:00
Owner

Two commits, milestone 328 steps 3 and 6 plus one CI defect found on the way.

What is in here

8a4af58 — the install path, written for someone who is not the operator.
README split into running-FC above the line and developing-FC below it, with requirements, first run, the extension, upgrading and troubleshooting on the running side. .env.example rewritten to say which values must change before exposure and how to generate one safely.

The substantive part is the no-auth posture. FC has no login — no User model, no session auth — which was a deliberate call for a single-operator tool and stays. It was nowhere in the docs, and the app stores live Patreon / SubscribeStar / Pixiv session cookies on accounts carrying a payment method. Anyone standing this up from the README could reasonably have put it behind a TLS-terminating proxy and considered it handled. It is now stated in all three places where someone decides where to bind the port: README's "Before you expose it", .env.example, and the compose header above the first service.

SECURITY.md claimed the opposite — it listed "a multi-user sharing ACL" among the things worth protecting, which is rule 47 applied to a codebase that does not implement it, and would have told a researcher FC holds a boundary it does not. Replaced with the real posture. EXTENSION_API_KEY was also dead config: config.py read it into a field nothing consumed, while the real key is generated into app_setting on first use and managed in the UI.

3590c47 — folder import stays retired, and a readiness probe that never probed.

The README described the missing folder-import button as a rough edge with a tracking issue, promising a fix that is not coming. Operator's call this session: the import-from-file surface was abandoned on purpose. Both places (README first run, the /import bind-mount comment) now record the retirement as the decision, name Subscriptions as the supported way to fill a new install, and describe /api/import/trigger as an unsupported escape hatch. #3367 cancelled.

Separately: ci.yml's integration job and baseline.yml both waited for Postgres with (echo > /dev/tcp/$PG_IP/5432). Those steps run under sh -e, where /dev/tcp is not a magic path but a filename that does not exist — so the probe could never succeed. Job 18035, a green run, enters that loop at 05:20:53 and leaves it at 05:22:53 by exhaustion rather than by connecting. Every integration run has paid a flat 120 s for a check that established nothing, then proceeded anyway. Replaced with a socket connect in python, and timing out is now a named failure instead of a silent fall-through. Measured after: 2.1 s and one sleep, on run 5212.

Also done outside the diff

Step 3's registry and release cleanup, on the operator's decision this session — 28 development-era releases deleted with their git tags kept, and the four orphan v26.06.0x images removed. :latest, :dev, :c-<sha> and :buildcache were re-listed afterwards and all still resolve.

Verification

CI green on 3590c47 across all three runs (5211, 5212, 5213) — lint, extension-version, backend unit, frontend build, integration.

The alembic baseline that main already carries is untouched by this PR. The operator has confirmed the live database reads alembic_version = '0089', which is the id the baseline claims, so alembic upgrade head is a no-op on it and the deploy is a normal one.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TTjbZZ6JirCMSaJzQV1RhA

Two commits, milestone 328 steps 3 and 6 plus one CI defect found on the way. ## What is in here **`8a4af58` — the install path, written for someone who is not the operator.** README split into running-FC above the line and developing-FC below it, with requirements, first run, the extension, upgrading and troubleshooting on the running side. `.env.example` rewritten to say which values must change before exposure and how to generate one safely. The substantive part is the no-auth posture. FC has no login — no User model, no session auth — which was a deliberate call for a single-operator tool and stays. It was nowhere in the docs, and the app stores live Patreon / SubscribeStar / Pixiv session cookies on accounts carrying a payment method. Anyone standing this up from the README could reasonably have put it behind a TLS-terminating proxy and considered it handled. It is now stated in all three places where someone decides where to bind the port: README's "Before you expose it", `.env.example`, and the compose header above the first service. SECURITY.md claimed the opposite — it listed "a multi-user sharing ACL" among the things worth protecting, which is rule 47 applied to a codebase that does not implement it, and would have told a researcher FC holds a boundary it does not. Replaced with the real posture. `EXTENSION_API_KEY` was also dead config: `config.py` read it into a field nothing consumed, while the real key is generated into `app_setting` on first use and managed in the UI. **`3590c47` — folder import stays retired, and a readiness probe that never probed.** The README described the missing folder-import button as a rough edge with a tracking issue, promising a fix that is not coming. Operator's call this session: the import-from-file surface was abandoned on purpose. Both places (README first run, the `/import` bind-mount comment) now record the retirement as the decision, name Subscriptions as the supported way to fill a new install, and describe `/api/import/trigger` as an unsupported escape hatch. #3367 cancelled. Separately: `ci.yml`'s integration job and `baseline.yml` both waited for Postgres with `(echo > /dev/tcp/$PG_IP/5432)`. Those steps run under `sh -e`, where `/dev/tcp` is not a magic path but a filename that does not exist — so the probe could never succeed. Job 18035, a **green** run, enters that loop at `05:20:53` and leaves it at `05:22:53` by exhaustion rather than by connecting. Every integration run has paid a flat 120 s for a check that established nothing, then proceeded anyway. Replaced with a socket connect in python, and timing out is now a named failure instead of a silent fall-through. Measured after: 2.1 s and one `sleep`, on run 5212. ## Also done outside the diff Step 3's registry and release cleanup, on the operator's decision this session — 28 development-era releases deleted with their git tags kept, and the four orphan `v26.06.0x` images removed. `:latest`, `:dev`, `:c-<sha>` and `:buildcache` were re-listed afterwards and all still resolve. ## Verification CI green on `3590c47` across all three runs (5211, 5212, 5213) — lint, extension-version, backend unit, frontend build, integration. The alembic baseline that `main` already carries is untouched by this PR. The operator has confirmed the live database reads `alembic_version = '0089'`, which is the id the baseline claims, so `alembic upgrade head` is a no-op on it and the deploy is a normal one. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01TTjbZZ6JirCMSaJzQV1RhA
bvandeusen added 2 commits 2026-09-02 11:25:09 -04:00
docs: write the install path for someone who is not the operator (#3271)
Build images / sign-extension (push) Successful in 4s
Build images / build-agent (push) Successful in 9s
Build images / build-ml (push) Successful in 29s
Build images / build-web (push) Successful in 23s
CI / lint (push) Successful in 3s
CI / extension-version (push) Successful in 4s
CI / frontend-build (push) Successful in 20s
CI / backend-lint-and-test (push) Successful in 30s
CI / integration (push) Successful in 3m42s
8a4af589f1
FC has no login — no User model, no session auth, nothing. That was a
deliberate call for a single-operator tool and it stays (operator, this
session), but it was nowhere in the docs, and the app stores live Patreon /
SubscribeStar / Pixiv session cookies on accounts that carry a payment
method. Anyone standing this up from the README could reasonably have put it
behind a TLS-terminating proxy and considered it handled.

So the no-auth posture is now stated three times, in the three places someone
decides where to bind the port: README has a "Before you expose it" section
above the install instructions, .env.example explains why there is no auth
variable in it, and the compose header says it before the first service.

SECURITY.md claimed the opposite. It listed "a multi-user sharing ACL —
instances can be shared" among the things worth protecting; there are no
accounts to share between. That was rule 47 applied to a codebase that does
not implement it, and it would have told a researcher FC holds a boundary it
does not. Replaced with the real posture, including that TLS without an
authenticating layer in front changes nothing.

Also corrected, all of it stale rather than wrong-at-the-time:

- EXTENSION_API_KEY was dead config. config.py read it into a field nothing
  consumed; the real key is generated into app_setting on first use and
  managed in the UI. Removed from config.py, compose and .env.example.
- .env.example pointed at docs/superpowers/specs/… — there is no docs/ dir —
  and described the extension key as "lands in FC-3", closed 2026-05-21.
- The /import mount comment described an FC-5 ImageRepo migration run from
  "Settings → Maintenance → Legacy migration", a surface with no frontend.
- README said the extension installs from Settings → Maintenance. It is on
  Subscriptions → Settings.

README is now split: running FC above the line, developing FC below it, with
requirements, first run, the extension, upgrading and troubleshooting on the
running side. First run documents the one real gap it found — a new installer
with a library on disk has no button to import it, only POST
/api/import/trigger, because the manual-scan UI was retired 2026-07-02 when
that stopped mattering for an established install. Filed as #3367.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017QHszn9H8VBvx5Ke8x1hvw
docs+ci: folder import stays retired, and fix a readiness probe that never probed
CI / lint (push) Successful in 3s
Build images / sign-extension (push) Successful in 4s
CI / extension-version (push) Successful in 3s
Build images / build-ml (push) Successful in 7s
Build images / build-agent (push) Successful in 13s
Build images / build-web (push) Successful in 7s
CI / frontend-build (push) Successful in 22s
extension / lint (push) Successful in 29s
CI / backend-lint-and-test (push) Successful in 49s
CI / integration (push) Successful in 1m57s
extension / lint (pull_request) Successful in 22s
3590c478f5
Two unrelated things, both found while closing out milestone 328.

**Folder import (#3367).** The operator's call, this session: the
import-from-file surface was abandoned on purpose and is not coming back —
"it has its own complexities that we didn't need." The README and the
compose comment both described the missing button as a rough edge with a
tracking issue, which promised a fix that is not coming. Both now say the
retirement is the decision, name Subscriptions as the supported way to fill
a new install, and describe /api/import/trigger as an unsupported escape
hatch for anyone who wants to script one.

**The CI readiness probe.** ci.yml's integration job and baseline.yml both
waited for Postgres with `(echo > /dev/tcp/$PG_IP/5432)`. Those steps run
under `sh -e` — act's default shell — where /dev/tcp is not a magic path but
a filename that does not exist. The probe could therefore never succeed: run
18035, a GREEN run, spends 05:20:53 → 05:22:53 in that loop and exits it by
exhaustion, not by connecting. Every integration run has been paying a flat
120s for a check that established nothing, and proceeding regardless.

Replaced with a socket connect in python (present in the image, no package
needed), and exhausting the budget is now a named failure instead of a
silent fall-through — rule 156.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTjbZZ6JirCMSaJzQV1RhA
bvandeusen merged commit 3e4d39b111 into main 2026-09-02 11:25:28 -04:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bvandeusen/FabledCurator#246