Commit Graph
229 Commits
Author SHA1 Message Date
Firehose Bot 7fda0455c1 compile deps in make setup so cold clones stay offline
Some deps download artifacts at compile time: rustler_precompiled
fetches the mdex_native NIF from GitHub during its first compile, and
NimblePublisher pulls mdex_native into both apps. Compiling inside the
deps target keeps that traffic inside setup - the explicit user-run
network step - instead of the first make check/test on a fresh clone.
2026-10-29 18:09:42 +00:00
Firehose Bot 0d344a4f57 make blog slug tests content-independent
Commit 1709cb7 deleted the pinned hello-world post and ten tests
silently rotted with it - invisible until now because the suite could
not run in this clone (incomplete deps, then the broken frontmatter).
The slug, banner, og-meta and tag tests now derive slug and title from
the compiled posts at runtime (newest live post, newest draft), matching
the existing latest_post_with_links pattern, so content churn no longer
breaks them.
2026-10-29 18:05:29 +00:00
Firehose Bot 97fc024a38 add make setup and network-free deps.check guard
mix deps.get contacts hex.pm even when everything is already installed
(the advisory check), so the everyday loops failed in offline/sandboxed
environments; and the root deps target only installed app's deps, never
blogex's.

make setup (root) installs Hex deps for both apps plus the app's JS
packages, once per clone, explicitly. check, test and test.coverage in
both apps now depend on a local deps.check guard instead: every package
pinned in mix.lock must exist in deps/, else fail loudly pointing at
make setup. AGENTS.md documents the new target.
2026-10-29 17:44:16 +00:00
Firehose Bot 7215cd6db0 fix split closing quote in intention-location-details frontmatter
8fa342e split the description's trailing ", onto its own line, leaving
the frontmatter invalid Elixir; NimblePublisher evals frontmatter at
compile time, so the app could not compile. Also drops the
“/” entities from the description (uncommitted WIP, kept
per plan).
2026-10-29 17:44:16 +00:00
Firehose Bot 8fa342e80d publish, and fix description 2026-10-29 17:00:29 +00:00
Firehose Bot 9029ead53a Merge branch 'main' of ssh://gitea.apps.sustainabledelivery.com:3022/mostalive/firehose 2026-10-29 16:52:06 +00:00
Firehose Bot 1709cb78a1 intention-location details pattern 2026-10-29 16:51:38 +00:00
Willem van den Ende e257d58541 yak(deps-upgrade-phoenixecto-and-postgrex-once-the-mix-120-xref-fix-ships-z3qh): install ecto_psql_extras for LiveDashboard Ecto Stats 2026-10-29 13:43:58 +00:00
Willem van den Ende df9597682c yak(deps-upgrade-phoenixecto-and-postgrex-once-the-mix-120-xref-fix-ships-z3qh): bump phoenix_live_dashboard to 0.9.1 2026-10-29 13:41:12 +00:00
Willem van den Ende f5faa8a3af yak(theme-explicit-light-is-overridden-on-dark-os-browsers-chip-backgrounds-are-dropped-pku7): theme: explicit light is overridden on dark-OS browsers; chip backgrounds are dropped 2026-10-29 13:07:08 +00:00
Willem van den Ende edba66239e yak(coverage-floors-re-measure-and-re-record-after-the-behavior-test-yaks-mgr8): coverage floors: re-measure and re-record after the behavior-test yaks 2026-10-29 10:38:36 +00:00
Willem van den Ende 9c0f33e6ca yak(behavior-tests-web-controllers-and-auth-edge-cases-o04i): behavior tests: web controllers and auth edge cases 2026-10-29 10:15:21 +00:00
Willem van den Ende b2bd6bc3aa yak(behavior-tests-web-core-components-uyju): behavior tests: web core components 2026-10-29 10:14:27 +00:00
Willem van den Ende ef8407b272 yak(credo-strict-tuned-config-both-apps-x02d): credo strict, tuned config (both apps) 2026-10-29 10:13:02 +00:00
Willem van den Ende 13e3186f58 yak(boundary-repo-as-sibling-boundary-web-repo-forbidden-tgrc): boundary: Repo as sibling boundary, web->Repo forbidden 2026-10-29 10:08:56 +00:00
Willem van den Ende 3ef38bc8fc yak(mutation-testing-with-muex-blogex-pure-app-code-1341): mutation testing with muex (blogex + pure app code) 2026-10-29 10:07:55 +00:00
Willem van den Ende 09da15c1df yak(sobelow-in-the-lens-pass-vr40): sobelow in the Lens pass 2026-10-28 23:22:07 +00:00
Willem van den Ende e292b4ebfb yak(ratchets-deferred-decisions-handoff-practice-ccjp): ratchets, deferred decisions, handoff practice 2026-10-28 23:14:18 +00:00
Willem van den Ende b72446b80e yak(behavior-tests-editorial-liveviews-microprints-editor-dashboard-llh3): behavior tests: editorial LiveViews (microprints, editor dashboard) 2026-10-28 22:27:59 +00:00
Willem van den Ende c04d8c856c yak(link-validator-never-sees-compiled-html-internal-link-validation-is-vacuous-ddd1): Link validator never sees compiled HTML — internal-link validation is vacuous 2026-10-28 22:08:45 +00:00
Willem van den Ende 4e7798c906 yak(make-checkverify-format-gate-rewrites-files-instead-of-checking-lnje): make check/verify format gate rewrites files instead of checking 2026-10-28 21:50:01 +00:00
Willem van den Ende a6a7b3a8c7 yak(pin-user-inspect-output-exactly-both-redacted-fields-shape-l0mg): pin User inspect output exactly (both redacted fields + shape) 2026-10-27 21:28:37 +00:00
Willem van den Ende a72d73f21c app: logout disconnects open LiveView sockets
`put_token_in_session/2` wrote only `:user_token`, so `log_out_user/1`'s
`if live_socket_id = get_session(conn, :live_socket_id)` was always false and
logging out left open LiveView sockets running. Write the socket topic
alongside the token, copying phx.gen.auth's format verbatim
("users_sessions:" <> Base.url_encode64(token)) so it matches both what
Phoenix.LiveView.Socket.id/1 reads and what log_out_user/1 reads. The reissue
path goes through the same function, so it follows the new token.

Tests (provider/reader agreement, both previously absent):
- log_in_user/3 stores the id derived from the session token
- fetch_current_scope_for_user/2 reissues the id with the new token
- log_out_user/1 broadcasts exactly one "disconnect" on that id
- the value written is the topic Socket.id/1 returns for the session the
  websocket receives (string keys)

Not tested end to end: a real disconnect needs the transport process, which
Phoenix.LiveViewTest does not start — Phoenix.Socket.__info__/2 handles the
broadcast (deps/phoenix/lib/phoenix/socket.ex:571) and
phoenix_live_view/test/client_proxy.ex never subscribes to the socket id topic.

Gate: make check + make verify green (app coverage 86.97%, blogex 75.16%,
crap sensors green).

Yak: logout-must-disconnect-existing-liveview-sockets-livesocketid-never-set-6fme
2026-10-27 09:56:25 +00:00
Willem van den Ende 2ba0b7bc48 app: CRAP scores as a Lens sensor (ex_crap)
The coverage export from `test.coverage` now also feeds a `crap` sensor,
second in app's VERIFY_SENSORS. It runs with MIX_ENV=test so it reads the
export's own environment instead of compiling a dev build and scoring a
different module set, and it guards on the export's existence because
ex_crap silently falls back to 0% coverage when the file is missing.

Baseline at ex_crap's default threshold (30): 23 files, 139 functions,
worst score 20.00 (CoreComponents.table/1, 0% - unused upstream scaffold).
No offenders, so nothing to refactor or cover yet.
2026-10-26 21:32:37 +00:00
Willem van den Ende a0692056bc demo skill: read the dev port from config; make deps installs JS packages
The skill assumed port 4000, but config/dev.exs serves on 8056 (and honours
$PORT), so a fresh demo run failed its liveness check and every rodney URL
pointed at the wrong port.

- demo skill: resolve DEMO_PORT from the app config with
  `mix run --no-start -e 'Application.get_env(:firehose,
  FirehoseWeb.Endpoint)[:http][:port]'` (Endpoint.config/1 raises without a
  started endpoint), derive $DEMO_BASE_URL from it, start the server on that
  port from app/, and use $DEMO_BASE_URL in every rodney example. The skill
  also points at .tmp/phx-demo.log and names the assets/node_modules
  highlight.js failure as a diagnosable cause.
- app/Makefile: new `assets` target that runs `npm install` only when
  node_modules/.package-lock.json is missing, and `deps` now depends on it.
  A fresh clone gets a working JS bundle from `make deps`/`make test`; later
  runs never touch the network, so offline runs keep working.

Verified: guard skips with node_modules present and installs after moving it
aside; the skill's DEMO_PORT command prints 8056 and follows PORT=9999;
make check and make test (179 + 162) green.
2026-10-26 21:08:00 +00:00
Willem van den Ende e3fc734862 External links: screen-reader hint on links that leave the blog
External links in post bodies already opened in a new tab and showed an
icon, but the icon is invisible to screen readers, so nothing announced
that the link leaves the site.

- blogex: ExternalLinks.rewrite/1 appends
  <span class="blogex-external-hint"> (opens in a new tab)</span> as the
  last child of every external anchor. No aria-label, so the accessible
  name still contains the visible link text (WCAG 2.5.3); the icon colour
  and 2.5.3 both hold. Idempotent: a second pass adds no second hint.
- blogex: anchors are now matched together with their closing tag
  (the hint goes inside), so a stray unclosed <a> is left alone.
- app: sr-only rule for .blogex-external-hint in .blogex-post-body. The
  split stays as before: blogex marks up, the host app styles.
- tests: hint cases in blogex (appended, per link, after inner markup,
  idempotent, not on internal/mailto/anchor links) + anchors without href
  (Blogex.ExternalLinks now at 100% line coverage), and an app test that
  the hint reaches the rendered post page. Two exact-string expectations
  updated for the intended markup change.

make test: app 179, blogex 162. make verify: green.
2026-10-26 20:28:16 +00:00
Willem van den Ende 4b4d0c491c app: exclude embed_templates wrappers and the release-only Application
Raises the measured total 86.17% -> 86.79% without touching a test, because the
excluded modules hold no behavior a test can observe:

- FirehoseWeb.{Blog,UserRegistration,UserSettings}HTML are `use` +
  `embed_templates` only; every function in them is macro-generated. Their
  TEMPLATES are already exercised through the controller tests.
- Firehose.Application: start/2 is proven by the suite booting at all, and
  config_change/3 runs only on a release hot upgrade.

Deliberately NOT excluded, despite being embed_templates wrappers:
FirehoseWeb.PageHTML (blog_label/1, post_base_path/1) and
FirehoseWeb.UserSessionHTML (local_mail_adapter?/0) carry real private logic, so
their sub-100% coverage is a behavior gap for the controller/auth yak, not macro
noise.

Also drops the now-dead Firehose.Checks.NoConnShadowing entry: lib_dev/ is no
longer compiled, so it is not measurable. Floor stays 86 (86.79 rounds down).
2026-10-26 20:02:45 +00:00
Willem van den Ende 9730987846 app: give credo checks one load path (fixes redefining-module warning)
lib_dev/ was both compiled (elixirc_paths for :dev and :test) and source-loaded
by credo through `requires:` in .credo.exs. Two load paths for one module means
that whenever _build/dev already holds the beam, `mix credo` warned:

    warning: redefining module Firehose.Checks.NoConnShadowing
    (current version loaded from _build/dev/.../Elixir.Firehose.Checks.NoConnShadowing.beam)

Keep the explicit contract and drop the accidental one: `requires:` is the
documented way for credo to load project checks, so lib_dev/ now leaves
elixirc_paths in every environment. Nothing under test/ referenced the check, so
the :test entry was dead as well, and credo compiles the file on every run
anyway, so the check still gets compiled — just once.

One-time migration for checkouts that already built it:
`mix clean` (or delete _build/dev) to drop the stale beam; until then the old
warning persists. Fresh clones are unaffected.
2026-10-26 20:01:33 +00:00
Willem van den Ende f54ce2fab7 app: note that CoreComponents.table/1 and list/1 are unused upstream scaffold
These two come from the upstream Phoenix generator and are worth keeping for
future data/admin screens, so they stay rather than being deleted as dead code.

The note also records why they look unused but aren't pointless: the collections
already in the UI are hand-rolled (editor_dashboard_live's drafts/scheduled rows
are bordered divs; Blogex.Components.post_index renders post previews and tag
lists itself). That is the fact a future reader needs before either deleting
these or writing yet another bespoke list.
2026-10-26 19:50:47 +00:00
Willem van den Ende abb712f8a2 app: coverage floor (86) + framework-glue exclusions
Measured before choosing: 86.17%, identical via `mix test --cover` and via the
exported sample + `mix test.coverage`, stable across seeds. Floor is the integer
below that, with the rule written next to it: a FLOOR, ratcheted up as
behavior-test yaks land, never lowered (a drop means the change or an exclusion
is wrong).

Exclusions are the modules the suite cannot or should not exercise, each
justified in the config comment: `use`-generated glue (Repo, Mailer, Telemetry,
ErrorHTML/ErrorJSON), the `use FirehoseWeb` macro, production release tasks
(Release), the lib_dev credo check (NoConnShadowing), and test scaffolding
(DataCase, ConnCase, AccountsFixtures, Test.FakeBlog). Everything else counts,
CoreComponents/controllers/LiveViews included.

Wiring matches blogex and the fast/push split: `test.coverage` runs the suite
once with `--cover --export-coverage default` (deleting stale exports first,
since `mix test.coverage` imports every .coverdata it finds and would pool
them), then the `coverage` sensor enforces the floor from that export. The
sensor guards on the export existing because `mix test.coverage` exits 0 when it
finds nothing — a floor check that did not run must not pass.
2026-10-26 18:40:09 +00:00
Willem van den Ende a9a02aa9ba app: hand-write the User Inspect impl so coverage can instrument it
`redact: true` makes Ecto derive an Inspect impl at the `schema` line.
Elixir 1.20.4 emits that whole derived impl on that one line, and OTP 27's
coverage instrumentation (sys_coverage) turns it into invalid Erlang
("variable '_2' unsafe in 'case'"), so `mix test --cover` aborted for the whole
app before reporting anything. Minimal repro, no Ecto needed:
`@derive Inspect` on a plain struct fails on Elixir 1.20.4 + OTP 27.3.4.19 and
works on Elixir 1.18.3 + the same OTP.

Writing the impl out by hand, one expression per line, keeps `inspect/1`
output byte-identical (Ecto/Elixir render redacted fields as
`#Mod<..., ...>`) and keeps redaction pinned by the existing test, and lets the
coverage sensor land. Revisit when the Elixir/OTP pins change.
2026-10-26 18:38:13 +00:00
Willem van den Ende 068911b4e8 make verify: add the Lens pass container (both apps, cheapest first)
Root verify runs check first, then a per-app verify in each Makefile: sensor
slots hooked to VERIFY_SENSORS (empty today, so nothing is claimed that is not
run) and then that app's suite. Measured: 9.9s wall, app 178 + blogex 156 tests.
2026-10-26 17:58:42 +00:00
Willem van den Ende a1ff6dbbac mix.lock: patch/minor dependency bumps (18 packages)
All within existing mix.exs constraints. Notables: bandit 1.12.5->1.13.1,
phoenix 1.8.15->16, phoenix_live_view 1.2.12->13, swoosh 1.28.1->1.29.0,
tailwind 0.4.1->0.5.1 (new bundled CLI - check CSS output after deploy).
Tests: 156 passing (app + blogex).
2026-10-26 12:53:33 +00:00
Firehose Bot 9fdb003521 converting to static site with one prompt 2026-10-23 09:32:40 +01:00
Firehose Bot d8cf81aeec mention I haven't tried Deepseek yet 2026-10-21 16:58:58 +01:00
Firehose Bot 5a9106b61e Merge branch 'main' of ssh://gitea.apps.sustainabledelivery.com:3022/mostalive/firehose 2026-10-21 14:53:50 +01:00
Firehose Bot aef57c54f9 my open weight models this month 2026-10-21 14:53:35 +01:00
mostalive 9050329685 Add link to fork, fix tags in other posts 2026-10-21 11:50:35 +01:00
mostalive 86d52aa420 add image to blog, fixed emacs drag and drop on linux 2026-10-21 11:19:31 +01:00
Firehose Bot ebf076c450 remove commas, fix description 2026-10-20 13:23:16 +01:00
Firehose Bot 628c032f0b Merge branch 'main' of ssh://gitea.apps.sustainabledelivery.com:3022/mostalive/firehose 2026-10-20 13:20:35 +01:00
Firehose Bot 8e1f5806cf video transcriber post 2026-10-20 13:17:50 +01:00
mostalive 8a8992603b Fix catherine breslin link 2026-10-15 14:57:31 +01:00
Firehose Bot 5d7eddbfef fix(build): resolve mise via PATH instead of hardcoded ~/.local/bin path
mise now lives at /opt/homebrew/bin/mise (Homebrew install), so the
hardcoded MISE_BIN default broke make test/deps/compile. Fall back to
PATH lookup, matching what the check target already did.
2026-10-15 13:43:26 +01:00
Firehose Bot c8a3713cca fix link 2026-10-11 14:40:45 +01:00
Firehose Bot 855bb37065 remove todo
can't find John's post on linkedin
2026-10-08 13:56:01 +01:00
Firehose Bot 38873bde8c will it blend - live 2026-10-08 13:39:09 +01:00
Firehose Bot 310a5c0afd Bump phoenix_live_view to 1.2.12, closing last security advisory
The microprints git dep now allows phoenix_live_view ~> 1.2, so the
app can take the CVE-2026-64941 fix (open redirect in
validate_local_url!/2, fixed in 1.2.9). No 1.1.x backport existed.

blogex test lock follows to 1.2.12 so the library is tested against
the version the app ships with. mix deps.get now reports zero
security advisories.
2026-10-08 09:50:49 +01:00
Firehose Bot 7869166841 Add Playwright e2e test setup and configs 2026-10-08 09:49:07 +01:00
Firehose Bot b972603143 Add draft blog posts on step size and TDD diagnostics
Both published: false. The 07-20 draft references a screenshot that is
not yet in the repo (roam-export image copying is still in progress).
2026-10-08 09:49:07 +01:00