Commit Graph

1289 Commits

Author SHA1 Message Date
admin 9e68e526e9 v0.316.2: two more leftovers on the data tab
gates / gates (push) Failing after 48s
Biztonsagi mentes was still a card — it sits directly in the tab, not inside a section, so the
.app-section scoping rule did not reach it. It is a section now.

The 2nd-copy heading still read '2. mentes beallitasa — <app>', because the locale key carries the
app name: it was a PAGE title, and a tab already says which app it is. New key
app_page.second_backup ('2. mentes' / 'Second backup'). This is the leftover the task named.

Found by looking at the rendered page, not the markup.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
2026-10-15 20:51:45 +02:00
admin 02252556b3 v0.316.2 CHANGELOG
gates / gates (push) Failing after 50s
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
2026-10-15 20:46:24 +02:00
admin f908eee2a3 v0.316.1: the settings tab's reused form markup loses the install page's boxes
gates / gates (push) Failing after 47s
The fields on Beallitasok are the install wizard's markup, which carries that page's card around
the whole form and one around every generated value. On a TAB those are sections, so the boxes come
off; the input itself is still a field, which is what tells the household it holds a value. Scoped
to .app-section so the install page — same column, its own form — is untouched.

Found in a browser by asking the page which elements still paint a background, rather than reading
the markup and guessing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
2026-10-15 20:45:57 +02:00
admin 006ceab58a v0.316.1: the asset tag actually reaches the dashboard pages
gates / gates (push) Failing after 48s
v0.316.0 shipped it dead. Every shell asked for `?v={{.AssetTag}}`, TestAssetTag_EveryShellUsesIt
passed, and the first live load through the public address rendered `/static/style.css?v=` —
EMPTY. addShellAssetData was called only by executeTemplateLang (the sign-in, claim, recovery,
guest-share and catch-all pages). The dashboard path had never needed it, because layout.html used
to ask for {{.Version}}, which baseData supplies; moving it to {{.AssetTag}} left nothing to
supply the value.

An empty buster is a CONSTANT. It would never have changed again — worse than the per-version one
it replaced, and invisible to a test that only checks the markup. executeTemplate now calls the
same function executeTemplateLang does, which is literally what the v0.255.0 comment above that
call asked for: "setting it at the single choke point every shell renders through means a new
shell cannot miss it". There were two choke points.

TestAssetTag_ReachesTheRenderedPage renders six real URLs through the production router and asserts
the buster is non-empty, 8 hex, and not a version. Red-proved by removing the call again: four
pages fail naming the empty value.

A PATCH VERSION, not a second push of 0.316.0 — the rule this release added, applied to its own
mistake rather than around it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
2026-10-15 20:41:09 +02:00
admin 48d8674876 v0.316.0 CHANGELOG; the push-once fact in this repo's unprompted-work rule
gates / gates (push) Failing after 49s
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
2026-10-15 20:33:22 +02:00
admin 7f3e58ff0a The app page as one column — the approved mockup
gates / gates (push) Failing after 49s
v0.315.0 worked and looked, in the operator's words, messy: boxes of different widths stacked down
the page, with the same card shape around things you act on and things you only read. The mockup
approved on 2026-10-15 replaces it, and each of its three rules has a reason:

  ONE COLUMN OF ONE WIDTH (820px). Differing widths read as a page assembled by accident.
  SECTIONS ARE HAIRLINES, NOT CARDS. A card says "this is a thing you act on"; most of an app page
    is a thing you READ, so a card there is a promise the content cannot keep.
  A BOX MEANS SOMETHING. Exactly two remain: blue when the app is waiting for the household,
    amber when something is risky. The exception-colour principle applied to shape as well.

What moved:
  - the hero loses its box: a 64px logo tile, the name at 26px, the tagline, then hairline chips
    (state, lifecycle, update) and meta text (the address, the last automatic update);
  - the tabs are links with a 2px blue underline under the open one — no pills, no fills;
  - sections are `padding: 28px 0` with a bottom hairline; rows are a 200px label column so every
    value on the page starts at the same x, and stack under 720px;
  - the after-start callout is now the FIRST thing on Beallitasok. A household opening a Plex that
    wants its claim code should meet the code box, not a Restart button;
  - "2. mentes beallitasa — <app>" and "<app> — Exportalas" are gone: they were the headings of
    pages that no longer exist, on a tab that already says which app this is;
  - the settings tab gains "Cim es kulcsok" with one address row, and the disabled subdomain input
    that said the same thing is skipped for an installed app (the install wizard still asks);
  - the "this app is already installed, the settings are read-only" BANNER becomes the hint under
    the fields it is about;
  - the install wizard gets the same back link, hero and column, so pressing Telepites does not
    land the household on a page that looks like a different product.

THE AUTO-UPDATE SUCCESS BANNER IS GONE. It was a full-width blue box above the tabs, level with
"the update failed" and "your files are missing". A success that asked nothing of the household is
a date, and it is now meta text in the hero. Every banner that DOES need a decision — a failed
update, a hold, lost files, a missing drive, an interrupted install — is untouched, above the tabs,
exactly where R-571 puts it.

Tests: TestAppPage_OneColumnLayout (one column, one aria-current, no card-shaped section, no
success banner), TestAppPage_AutoUpdateSuccessIsMetaNotBanner, TestAppPage_CalloutsOnlyForAskAndWarn
(one blue callout on a waiting app and it comes first; one amber on a same-disk backup; none on the
good case). Four red-proofs recorded in REPORT.

app_row_dedup_gate convicted `.app-row`, correctly: that class already means "a row in the app
list". The app page's label/value row is `.app-field-row`. Restoring the list's own rule after an
over-broad rename was part of the fix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
2026-10-15 20:29:56 +02:00
admin 9cc7ffcf3b A version number is pushed once, and every build addresses its CSS differently
gates / gates (push) Failing after 44s
MEASURED FIRST (audits/app-page-2026-10-15b/P0/VERDICT.md). The tab bar rendered unstyled through
the public address for one reason, and it was not the box: exactly one guest runs 0.315.0 and it
runs the registry's current digest (8887343011d6, identical to the registry's). The floor is still
0.314.0, so nothing else could have taken it.

What it was, in four measured facts:
  1. the stylesheet URL is /static/style.css?v={{.Version}} -> ?v=0.315.0 for all THREE different
     0.315.0 builds (e66d466, fe0228c, db52f5a), the first of which had no .app-tabs rules at all;
  2. the origin sends NO validator at all (ETag present = 0, Last-Modified present = 0), so a
     cached copy cannot be revalidated - it can only expire;
  3. Cloudflare caches that URL (cf-cache-status HIT, age climbing) and rewrites the browser TTL
     from the origin's 3600 to 14400 - four hours;
  4. the session's first request returned cf-cache-status EXPIRED, which only happens when the edge
     holds an entry that has aged out.

Origin, edge and box now agree byte-for-byte. The stale object itself is gone - that first probe
forced its revalidation - and the REPORT says so rather than claiming a HIT nobody can reproduce.

THE FIX IS IN TWO PARTS, NEITHER OF WHICH IS PURGING A CACHE:

build.sh refuses to push a version that already exists, before building, for --push and
--multiarch. A registry that cannot be asked is a refusal too: proving the tag is new is the point,
and "I could not ask" is not that proof. Local builds are untouched - reusing a version while
iterating is normal. scripts/test_build_push_once.sh drives the real build.sh with a fake docker on
PATH over six cases; red-proved twice (check deleted -> a present tag builds and pushes; an
unreachable registry treated as absent -> two cases fail).

assetTag() now hashes version + GitCommit + BuildTime, and EVERY shell's stylesheet link uses it
(seven of the nine asked for ?v={{.Version}}; only the two stranger-facing share pages already had
it). It stays opaque and 8 hex, because the share pages are reached by a capability URL and naming
the build to whoever holds one is a gift to somebody hunting a known fault. Cache-Control is
unchanged: the new address is the fix, not a shorter cache.

The parity harness normalises the asset tag on BOTH sides of the comparison, as it already does for
the per-session CSRF token, so all 148 fixtures stay byte-identical on disk and stop depending on
which build rendered them. The same normalisation is applied at the second comparison site in
i18n_wiring_test.go, which had the same assumption.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
2026-10-15 20:08:01 +02:00
admin 83392064ae REPORT + CONTEXT for v0.315.0: the live walk on demo-hp, and the two defects only a browser found
gates / gates (push) Failing after 46s
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
2026-10-15 19:32:47 +02:00
admin db52f5a4cf v0.315.0: close the log tab's <script> — the live poller was dead, and a test now says so
gates / gates (push) Failing after 49s
FOUND IN A BROWSER. The log tab's body was lifted out of the old logs.html by line range and the
range stopped one line short, so the closing </script> never came with it. Everything downstream
agreed the page was fine:

  - html/template parsed it,
  - the page rendered and looked right,
  - TestAppPage_EachTabRendersItsOwnContent found `setInterval(window.fetchLogs` exactly where it
    expected it, because the TEXT was there.

Chrome refused the whole block with "SyntaxError: Unexpected token '<'" at the `</div>` that
followed, so the live log never refreshed. A marker proves a string is present; it does not prove
the browser will execute it.

TestAppPage_ScriptTagsAreBalanced now counts <script> against </script> on all seven app-page URLs
and checks the last block is closed. Red-proved by removing the tag again: it fails naming the logs
tab, 3 opened and 2 closed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
2026-10-15 19:27:21 +02:00
admin fe0228c877 v0.315.0: style the app page's tab bar, and reuse the hero classes that already have rules
gates / gates (push) Failing after 46s
FOUND IN A BROWSER, and findable no other way. Every endpoint-level marker passed and the page was
unusable: the tab bar rendered as four bare underlined links run together, and the app logo filled a
third of the screen. The shell had been written with new class names — app-hero, app-hero-logo,
app-tabs — and only the first two of those had any CSS at all, under the names the design system
already uses.

  - the shell now reuses .app-info-hero / .app-info-logo / .app-info-hero-text, which carry the
    80px logo box, the hairline border and the 2px radius. Inventing a parallel name is what left
    the logo unsized; REUSE.md's first rule, learned again.
  - .app-tabs / .app-tab / .app-tab-active are genuinely new and are now styled to design system
    v2: 2px radius, hairline --line border, no shadow, --text-2 for an inactive tab and
    --blue-bright only for the one the household is on (blue marks where you are, not a deviation),
    the active tab sitting on the bar's own line, and a narrower gutter under 640px.
  - .after-start-card gets a blue left hairline — it is a request, not a fault, so no amber.
  - .app-faq gets its dt/dd rules.

TestAppPage_DeployedDefaultsToSettings sliced the header at `class="app-hero"`; it now slices at the
reused class and fails loudly if either marker is gone, instead of slicing on -1. The 36 app-page
parity fixtures are recaptured — and no other fixture moved, which is the evidence that the shell
change reaches only the app page.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
2026-10-15 19:04:57 +02:00
admin e66d4669d6 v0.315.0: one app page with four tabs; the guide the catalog can carry; no Raspberry Pi badge
gates / gates (push) Failing after 47s
An app was six pages — details, install/settings, logs, export, the per-app backup panel and a
details card for moving data — and every "Vissza" on them went to the app LIST, so there was no way
back to the app you were looking at. It is now ONE page with four tab URLs under /apps/{slug}/,
one shared header and one set of banners.

  settings  Mukodes (Start/Restart/Stop, Stop confirms) + the cards that want something from the
            household + the install-time and optional settings. The default for an installed app,
            RENDERED at the bare URL and never redirected to.
  data      the data folders, move to another drive, the nightly copy, the 2nd-copy setting, export
  guide     tagline, screenshots, use cases, first steps, the catalog's guide, the FAQ, the docs
            link — and the WHOLE page for an app that is not installed
  logs      the log, and the only tab whose poller runs

The tabs are links, not panels: a link in an alert has to land ON a tab, and the log poller must not
run on the other three. Start/Restart/Stop left the page header, where they read as menu buttons.

The old /stacks/{name}/{deploy,logs,export,backup} GETs answer 302 — never 301, which a browser
caches beyond anyone's reach — to the tab that now holds them, query string carried through, with
name->slug resolved through the stack list rather than assumed equal. Every POST on those paths is
untouched: the backup form, the app-email toggle and the reveal endpoints keep their URLs.

A value asked AFTER the app starts is now generic (D2). The catalog marks a field `after_start: true`
and supplies its label; the ACTION is Go, in a registry keyed by slug + env var. The catalog can
never declare what runs — a declared field with no registered action renders nothing, POSTs 404 and
logs one WARN with the env var KEY, never the value. A red-proof found the second half of that guard
unpinned: deleting the "the catalog must have DECLARED this field" check left the suite green, and a
POST for an undeclared field then reached Plex and opened the setup gate.
TestAfterStart_RegistryAloneIsNotAnInvitation pins it.

New catalog block app_info.guide (sections + faq + checked_version), parsed, localised field by
field and rendered with the household's own address filled in. It renders only when checked_version
names the image tag its author clicked through. No template carries one yet.

The Pi and "csak x86" badges are gone; PiCompatible and the catalog key stay this release, or a box
on 0.314.0 would read "csak x86" on every app (R-1067).

template_id_gate.py now follows {{template}} includes, with a scope decoy proving the walk did not
become vacuous.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
2026-10-15 18:37:50 +02:00
admin 85f65c70d8 v0.314.0: CONTEXT and REPORT after the release (floor 0.314.0 raised by CC's token at 13:11 UTC)
gates / gates (push) Successful in 46s
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-15 15:17:51 +02:00
admin 97c992ad44 v0.314.0: the R-1060 web test (a fake Plex that refuses the name „plex”), left out of 17863fe
gates / gates (push) Successful in 47s
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-15 14:34:46 +02:00
admin 17863fe8bc v0.314.0: a restore puts the setup gate back as it was (R-1057); a test build moves with the floor (R-1053); Prowlarr links itself (R-1058); the box claims Plex by address (R-1060)
gates / gates (push) Successful in 47s
MinAgent 0.155.0 (unchanged). Tests red-proved by mutation (A: 10, B: 7, C: 1, C2: 2).

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-15 14:34:33 +02:00
admin e209a8d724 Rule file: a release needs no golden; the floor carries it after the three test boxes; golden weekly (09 §3 decision 250, operator 2026-10-15)
gates / gates (push) Successful in 44s
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-15 11:43:16 +02:00
admin cac92a407e v0.313.0: media apps on every drive, drive events, a real restart, Plex without the race — release notes (MinAgent 0.155.0); golden next (bake → vouch → floor)
gates / gates (push) Successful in 44s
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-15 10:48:58 +02:00
admin f327bc53a9 after_start deploy fields: asked after the start by this controller, still required for older ones (R-1028/R-1045, security review of catalog 0188430)
gates / gates (push) Successful in 47s
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-15 10:32:51 +02:00
admin 372d6e5994 Plex (R-1045): the controller asks Plex itself whether it is claimed — after the claim and on the household's „Kész”; no template probe (an older controller would refuse the press forever)
gates / gates (push) Successful in 45s
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-15 10:29:47 +02:00
admin 37ffa3beb5 Safe removal (R-1044), found on Tester 1 G4: the drive gate leaves a safely removed drive alone (no false RETURNED/ABSENT, no mail); presence = backing device, not the agent's state
gates / gates (push) Successful in 46s
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-15 10:25:08 +02:00
admin a09cab124a mediawire: qBittorrent 5 answers a good login with 204 — accept it (found on Tester 1, Part G1); fake answers 204 like the app
gates / gates (push) Successful in 41s
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-15 10:02:26 +02:00
admin f580d88a14 Media build part 2 (unreleased): drive wiring in every app (R-1024/R-1037), old-install repair (R-1047), drive events notice + real restart now/later + stream check, file browser lets go of dead/removed drives and recreates on return (R-1038), safe removal keeps the drive (R-1044), Plex claim on the running server + probe accept (R-1028/R-1045)
gates / gates (push) Successful in 45s
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-15 09:54:49 +02:00
admin 78c894234c Media build part 1 (unreleased): real restart (R-1026), media apps on every PRESENT drive via an owned compose override (R-1023), dead-drive check from mountinfo, removal never deletes shared/:ro binds (R-1027), safety list knows userdata (R-1032), no drive question for media apps (R-1031)
gates / gates (push) Successful in 46s
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-15 09:25:43 +02:00
admin 331be17e1e Rule file: bake first — bake → vouch → floor, never a floor with no golden (09 §3 decision 247, operator 2026-10-15)
gates / gates (push) Successful in 49s
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-15 08:18:12 +02:00
admin 8bc7ec54cd v0.312.0: every public name answers only over https; HSTS one day (R-1033, P1)
gates / gates (push) Successful in 48s
forwarded.yml: felhom-forwarded is now a chain [felhom-https-only (redirectScheme https, 301 when the trusted tunnel
says X-Forwarded-Proto: http), felhom-forwarded-headers (the clean-up + HSTS 86400, no subdomains, no preload)] plus a
priority-1 catch-all router for unknown names over http. traefik.yml unchanged; hot-loaded.
Tests red-proofed. Evidence: felhom.eu documentation/audits/https-only-2026-10-14/.
2026-10-14 22:39:58 +02:00
admin 9b95e8e09b REPORT: R-1007 — the repair after an unclean boot, proven live on demo-hp
gates / gates (push) Successful in 42s
Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
2026-10-14 17:52:20 +02:00
admin 3b85a0c29a v0.311.0 (before the build): the repair's commands run quietly — no household file name can reach a log or the operator event
gates / gates (push) Successful in 50s
Security review of 8d862e4: compose's shared runner logs a failed command's stdout and puts its
stderr in the error, and that error became the event's `problem`. The after_unclean_boot commands now
run through a quiet runner (nothing logged, stderr discarded) and `problem` keeps the exit code only.
TestAUB_AFailingCommandLeaksNoOutput, red-proofed.

Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
2026-10-14 16:58:20 +02:00
admin 8d862e4e69 v0.311.0: after a power cut, an app repairs the files the cut left empty; the household sees lost photos (R-1007)
gates / gates (push) Successful in 52s
New template block after_unclean_boot (decision 236): once per controller start that followed an
UNCLEAN host boot (crashboot's own verdict, after the 15-minute crash grace; a normal or unknown boot
never runs it), each app with the block rebuilds ONLY its zero-byte files (scan: regular files, no
symlinks, its own filesystem; ids appended to the app's own command in batches; one retry, then
reported) and its own lost-file check is read. The household sees lost files (name, date taken) on
the app page until dismissed; the operator gets app_repaired_after_crash with counts only. Skips,
with the reason, an unproven image, an unknown key, an app not running. MinAgent 0.155.0 unchanged.
Tests red-proofed (14 guards). One new parity fixture (the new card only).

Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
2026-10-14 16:47:13 +02:00
admin acbbf4b305 REPORT: the machine came back by its power button; the hub ended the hold (R-998 live proof complete)
gates / gates (push) Successful in 49s
2026-10-14 00:05:58 +02:00
admin e24430cce5 REPORT: power-off (R-998) released and proven on the N100
gates / gates (push) Successful in 48s
2026-10-13 21:41:33 +02:00
admin 201f936e9a v0.310.0: „A gép kikapcsolása" — the household turns the whole machine off (R-998); honest restart text (R-999)
gates / gates (push) Successful in 48s
POST /api/server/poweroff (dashboard login, POST only, the typed word KIKAPCSOLÁS / TURN OFF)
→ agent POST /host/poweroff (MinAgent 0.155.0; hidden for an older agent). The controller refuses
during its own backup/restore/app update; the agent's reasons are shown as household sentences.
„Kiszolgáló újraindítása" becomes „A Felhom újraindítása" and says it restarts the Felhom part;
/api/server/reboot is POST only (R-983). Tests red-proofed; parity fixtures regenerated on purpose.
2026-10-13 20:17:30 +02:00
admin 1b2f74c52f v0.309.0: the default list completes groups 1 and 3 for households with no saved list (operator Q1); REPORT
gates / gates (push) Successful in 46s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-12 17:25:12 +02:00
admin 7626a28de3 v0.309.0: the fill warning reaches the household in its own language; the root-filesystem disk event pinned end to end (R-521 F7)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-12 17:11:53 +02:00
admin 402fa41e45 v0.309.0: re-capture the two notification-page parity fixtures; capture settings_notifications_groups_custom (R-388 slice 1)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-12 16:50:42 +02:00
admin 462196e29b v0.309.0: the notification page shows three group switches; details and cooldown under Részletek (R-388 slice 1, decision 200)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-12 16:50:41 +02:00
admin 68294ecb6f REPORT: v0.308.0 (the operator's answers, 2026-10-12)
gates / gates (push) Successful in 44s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-12 15:42:31 +02:00
admin faef8f8a91 v0.308.0 (R-554, held-back-able): recovery-info.txt points at the dashboard's Restore page and the recovery code; the first-boot setup wizard is deleted
Operator ruling 2026-10-12 (S27, 09 §3 decision 222). The operator approves the Hungarian text before
release. A box whose first ingestion failed now serves one bilingual waiting page and retries every
minute instead of the wizard. Own commit so the lead can hold it back.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-12 15:38:28 +02:00
admin fd28d70bff v0.308.0: controller batch 2026-10-12 — clear-address warning (R-922), secret sweep over every page (R-255), read_failed (R-266), no NVMe heat band (R-333), share globe (R-577), Hungarian dates and numbers (R-562), lost-drive option pinned (R-521)
Operator rulings 2026-10-12, 09 §3 decisions 196, 204-207, 223, 227. MinAgent 0.131.0 unchanged.
R-255's sweep found one leak, fixed here: an optional-config secret_input was rendered into its
settings page; it is now revealed on demand. Hungarian parity fixtures re-captured once for R-562.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-12 15:13:59 +02:00
admin dcd89364a4 REPORT: v0.307.0 released and delivered (2026-10-10 afternoon)
gates / gates (push) Successful in 1m19s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-10 15:24:38 +02:00
admin fc6466a50a v0.307.0: after a restart the Databases table lists each database once, not every pre-restore undo copy
gates / gates (push) Successful in 1m14s
Seen on demo-hp 2026-10-10 (adventurelog x4, bookstack x4). The synthesised run skips IsUndo files; only undo copies
-> no synthesised run. Two tests, both red-proved. v0.306.0 (R-570) was built but never delivered; 0.307.0 carries it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-10 15:19:43 +02:00
admin 9e5b88146e v0.306.0: R-570 — the off-site note decides on its kind only; the pre-0.251.0 text fallback is deleted
gates / gates (push) Successful in 1m14s
Fleet condition read on each box's settings.json 2026-10-10 (offbox.last_success ~02:16Z on 0.304.0).
Red-proof: the new no-kind row of TestR553_StaleNoteDecisionSurvivesWordingChange failed against the fallback.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-10 15:08:42 +02:00
admin c255195e37 REPORT: v0.305.0 released and delivered (2026-10-10)
gates / gates (push) Successful in 1m22s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-10 11:06:55 +02:00
admin 1cb43a21a2 v0.305.0: release entry (R-921 pre-check, R-922 email_cleared); MinAgent 0.131.0
gates / gates (push) Successful in 1m4s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-10 09:55:30 +02:00
admin b3a879b50e rules: "The system poster stays true" (section 6, all five copies identical)
gates / gates (push) Successful in 1m14s
The shared rule file carries the same wording in felhom.eu, felhom-controller,
felhom-agent, app-catalog-felhom.eu and the workspace root on DooPlex --
"change all five or none" -- so this is this repo's copy of a rule added in
felhom.eu a08bd3cbd5.

A session that changes a fact listed in
architecture/felhom-system-poster.facts.md (a machine, a role, a traffic path,
a backup tier, a time, a retention, a key, a known gap) updates that file in
the same commit; fixes the poster's text if the change is text only; or adds
"System poster needs a refresh: <what changed>" to STATUS. The report names
which of the three it did.

The poster is drawn in Claude Design and nothing in the repo renders it, so
scripts/poster_facts_gate.py only WARNS when the facts outrun the drawing --
it never fails a push, because a refresh needs the operator and another tool.

Verified identical to the other four copies by diff, before and after.
2026-10-09 18:10:12 +02:00
admin ec9b997151 controller (unreleased): R-921 check-first pre-check (no stop while another tier's job is in flight); R-922 email_cleared on a household's deliberate clear
gates / gates (push) Successful in 1m0s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-09 12:57:34 +02:00
admin 13eeb484ab REPORT: v0.304.0 released, delivered, D1/D3/D4 proven live (2026-10-09)
gates / gates (push) Successful in 1m11s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-09 08:36:57 +02:00
admin d7bfdccf57 v0.304.0: the decision sheet (D1, D3, D4, D8), R-899, R-304, three layout fixes — release entry
gates / gates (push) Successful in 1m7s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-09 06:56:22 +02:00
admin 3f84f82c3d R-893: hold the app after ANY failure once the definition or a volume moved; hold persisted before the stop; run_job done says it ran, not what it found (security review)
gates / gates (push) Successful in 56s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-08 15:13:04 +02:00
admin d3e17e9b2e CHANGELOG/README/REUSE/REPORT: the decision sheet D1, D3, D4, D8 (unreleased)
gates / gates (push) Successful in 1m0s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-08 14:49:27 +02:00
admin e06680b797 Operator actions in the report reply (D1, R-314/R-279/R-177, decision 185)
The hub may ask the running controller for a CLOSED list of actions,
carried in the report ACK (operator_actions) and answered on the next
report (operator_action_results): offsite_backup_now, abandon_stop,
abandon_extend (1-30 days), run_job (fill-watch, offsite-integrity,
offsite-proof, disk-health-check). Unknown action/job/argument -> refused,
nothing called. Once per id (in memory; every action is safe to repeat).

- internal/report/opactions.go: the executor; results re-sent until the
  hub stops listing the id.
- scheduler.RunNow: refuses unknown / already-running jobs; OnDemand(ctx)
  makes an operator's offsite-integrity run even when not due.
- ExtendAbandon never shortens the countdown and refuses in the hub phase;
  StopAbandon reports failure when the hub cancel failed (it said success).
- Report ACK read cap 4 KiB -> 64 KiB (an ACK over the cap dropped every
  field in it).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-08 14:49:27 +02:00
admin 63441f0a69 R-893 slice 1: a failed off-site replay after files/volumes/version moved holds the app
Decision 192 (D8, option C). After a failed off-site database replay whose
rollback worked, but where the snapshot's definition was written or a named
volume was replaced, the app is no longer started on the mixed state:
the live definition is written back, the database service stopped, and the
app held (HoldReasonRestoreMixed) for support. The sentence (hu+en) says the
app needs help and no longer claims the data is back as it was. The operator
gets a backup_run_failures mail (leg restore-hold-mixed).

The plain case (no version change, no volume replaced) keeps today's
behaviour (TestR379_ScenarioA). Red-proofed: r893_mixed_restore_test.go.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-08 14:49:27 +02:00