fix: harden node upgrades and prepare 1.9.0-alpha

This commit is contained in:
archipelago
2026-10-05 12:43:49 -04:00
parent 138a541d01
commit daac47cac4
129 changed files with 9910 additions and 794 deletions
+42
View File
@@ -0,0 +1,42 @@
# Private signed-catalog qualification
Use this only on explicitly selected development/acceptance nodes. It permits
testing a release-root-signed catalog before fleet publication. It does not
publish an app image, change the update mirrors, replace the trust anchor, or
authorize an unsigned catalog.
Set `ARCHY_APP_CATALOG_CANDIDATE` in a management-service systemd drop-in to an
absolute local catalog path. Keep that file readable by the service and outside
temporary storage if testing reboot persistence. The file must be at most 4 MiB
and carry a signature verified against the configured release-root anchor.
Malformed, missing, unsigned, tampered and wrong-key candidates fail before
replacing the previous cached bytes. An invalid explicitly selected candidate
does not fall back to the public catalog. The previous cache remains available;
inspect the refresh error rather than assuming the candidate was accepted.
Before activation, record the exact candidate hash, service binary hash, native
Bitcoin/LND identities and start times, app configuration, and existing catalog
cache/drop-ins. Back up persistent state before any app runtime migration.
Verify the candidate signature with `archipelago ceremony verify PATH` and
retain the original signed bytes. A private signing ceremony is not publication
approval.
After management restart, verify:
- Cached bytes exactly equal the signed candidate and still verify.
- Desired app manifests select the expected capability-compatible variant.
- Changed apps migrate through their supported lifecycle, with state backups.
- Native wallets, intentionally stopped/uninstalled apps and unrelated services
retain their previous state.
- App requests succeed from the actual caller/container namespace; container
health alone is insufficient.
- Repeated reconciliation, app restart, and separately arranged node reboot
preserve routing, state, certificates and management isolation.
The setting intentionally pins catalog selection. Track its removal as part of
release completion: after the tested catalog is published and verified, remove
only the qualification drop-in, reload systemd, restart management, and confirm
the normal public refresh returns the expected signed catalog. Do not leave the
override behind to silently prevent future app updates. For an aborted test,
restore the reviewed previous catalog/runtime/configuration together; removing
the override alone can reintroduce older manifest settings.
+43
View File
@@ -167,3 +167,46 @@ and observed its explicit acknowledgement. The owner then recorded receipt in
`/tmp/npm-release-handoff-ack.txt` and in the acknowledgement section above.
Publication remains held for the NPM release gate. Unavailable external acceptance
must be stated explicitly and cannot be silently treated as passed.
## Urgent public dashboard exposure gate — 2026-10-01
Investigator reports the Angor relay hostname reached the default Archipelago
login because its certificate existed without a corresponding host-nginx route.
The investigator owns the immediate Shorty nginx repair; the release session
will not modify that configuration concurrently. Exact final evidence is pending.
- [ ] Unknown public HTTP Host / TLS SNI and direct public-IP requests cannot
expose the dashboard, login assets or RPC, including IPv6 and any trusted
reverse-proxy/tunnel path. Test spoofed forwarding headers explicitly.
- [ ] LAN/private/tailnet dashboard access remains available as intended.
- [ ] Public HTTP ACME challenge access survives those restrictions.
- [ ] NPM host creation/edits automatically propagate HTTP/TLS routing.
- [ ] Relay hostname serves the intended relay and WebSocket upgrade using its
correct certificate; certificate existence is not route acceptance.
- [ ] These protections survive manager/nginx restart, renewal and OTA/ISO.
## Live security containment and project discovery follow-up
2026-10-01: relay certificate existed but named public route was absent; default
HTTP/HTTPS vhosts exposed the dashboard to public clients, including direct WAN
IP access. Investigator added live `angor-relay-npm.conf` forwarding TLS cert11
to loopback8091 with WebSocket upgrade; added `00-dashboard-source-guard.conf`
private-source geo/map guard to both management default vhosts, preserving public
ACME challenge paths. Backup: `/etc/nginx/sites-available/archipelago.before-public-guard-1790879144`.
Nginx syntax validation/reload passed. External tests: public IP root and RPC
404 over HTTP and HTTPS (IP HTTPS certificate validation bypassed only for this
negative routing probe); spoofed private Host, X-Forwarded-For and X-Real-IP and
unknown Host POST RPC all404. Tailnet dashboard200; indexer health200 height969475;
relay trusted TLS NIP11 metadata200, WebSocket101, read-only Nostr REQ returned EOSE.
These are live containment results, not fleet/IPv6/reboot/security-audit completion.
Release owner acknowledged security scope in `/tmp/npm-release-handoff-ack.txt`.
User then reported no Angor projects after changing BOTH indexer and relays.
Read-only kind3030 subscription limit5: new relay returned zero events + EOSE;
`wss://relay.angor.io/` returned five events + EOSE. Advised retaining original
Angor relays alongside own relay; a newly hosted relay does not automatically
contain global project metadata. Full app project discovery acceptance remains
required. Also observed own `/api/v1/query/Angor/projects?limit=10` returns404;
reference MempoolIndexerAngorApi.GetProjectsAsync uses this older specialized
route, whereas current deployment docs recommend stock Mempool. Verify actual
client version/discovery path rather than claiming fees/health prove compatibility.
File diff suppressed because it is too large Load Diff
+529 -1
View File
@@ -1,4 +1,6 @@
# Archipelago 1.8.23-alpha acceptance
# Archipelago 1.9.0 acceptance
The operator changed the release target from 1.8.23-alpha to **1.9.0**. This file retains its historical path so handoff links remain valid.
Status: PREPARING. Do not publish until artifact checks and offline signatures pass.
@@ -58,3 +60,529 @@ The release owner acknowledged `docs/npm-certificate-handoff-20261001.md` in
were reported by the operator; durable data-path resolution, safe host routing,
automatic certificate renewal/reload, and the handoff acceptance matrix remain
required before publication. Earlier authorization does not waive this new gate.
## Urgent public dashboard exposure gate — 2026-10-01
Investigator reports the Angor relay hostname reached the default Archipelago
login because its certificate existed without a corresponding host-nginx route.
The investigator owns the immediate Shorty nginx repair; the release session
will not modify that configuration concurrently. Exact final evidence is pending.
- [ ] Unknown public HTTP Host / TLS SNI and direct public-IP requests cannot
expose the dashboard, login assets or RPC, including IPv6 and any trusted
reverse-proxy/tunnel path. Test spoofed forwarding headers explicitly.
- [ ] LAN/private/tailnet dashboard access remains available as intended.
- [ ] Public HTTP ACME challenge access survives those restrictions.
- [ ] NPM host creation/edits automatically propagate HTTP/TLS routing.
- [ ] Relay hostname serves the intended relay and WebSocket upgrade using its
correct certificate; certificate existence is not route acceptance.
- [ ] These protections survive manager/nginx restart, renewal and OTA/ISO.
## Additional isolated security checks — not deployed
The management source-guard prototype passed five unit checks including legacy
address-specific HTTPS, idempotence, backup permissions and syntax/reload rollback.
An actual nginx instance in a private network namespace passed 120 negative
HTTP/TLS cases across IPv4/IPv6, raw/unknown/spoofed Host/SNI and forwarded headers,
including POST RPC and WebSocket upgrade requests. Exact ACME token reads,
private LAN/tailnet/ULA access, named public HTTP app routing and reload passed.
These are scoped checks, not complete fleet, trusted-tunnel, reboot or artifact
acceptance. Shorty's containment was not modified.
The NPM storage/routing prototype passed eight focused tests: fresh/flat/nested/
custom mount selection without mutation, ambiguity/wrong-mount refusal, corrupt
or uninitialized database preservation, duplicate/missing mounts, deleted/disabled
host exclusion, domain injection rejection, and rejection of mixed public and
loopback listener bindings. Automatic application/migration and end-to-end NPM
security/routing remain unfinished and block release.
Final Angor handoff was read and acknowledged in
`/tmp/angor-final-handoff-ack.txt`; see `angor-client-acceptance-20261001.md`.
One complete project flow is investigator-verified; 34 original announcements
remain unrecovered from queried sources. Full recovery acceptance remains open.
## Additional Angor public explorer gate
- [ ] Public indexer hostname serves Mempool UI and its assets/deep links/live
WebSocket updates while preserving Angor API/CORS/broadcast/readiness.
- [ ] Existing stack reused; no duplicate Mempool app/database and no management
or Bitcoin RPC exposure.
- [ ] Documentation/catalog/runtime metadata and exact OTA/ISO reflect the tested
implementation; repeat official-client browser acceptance afterward.
Confirmed official deployment guide describes a shared frontend/API origin.
Current adapter 1.0.1 is API-only; this requirement is not yet implemented.
## NPM real-image integration progress
Disposable real NPM API tests passed for both flat and legacy nested `/data`
layouts: initial account/host creation, multiple domains, custom location,
forwarded-client spoof rejection, exact challenge file access under forced HTTPS,
trusted TLS and WSS upgrade/frame, certificate replacement/reload, password and
network access lists, disable/enable/delete propagation, and restart with the
original database and account authentication preserved. Local fixture certificates
are not public Let's Encrypt staging issuance/renewal evidence; that gate is open.
Certificate replacement initially failed because the updated bridge could not
complete the upstream TLS request after replacing the fixture certificate.
Reloading and validating NPM's own TLS listener on certificate fingerprint changes,
as well as host nginx, resolved the test. Rollback/retry unit coverage was added.
The initial dev guard deployment changed only the inactive sites-available copy;
private HTTP 200 and unchanged entry bytes were insufficient acceptance evidence.
A later public-ingress-marker probe caught this: it incorrectly returned 200.
The resolver now chooses the active sites-enabled copy or resolves its symlink
without replacing the link. Guard backups live outside nginx include directories.
After the correction, live private requests return200 and marked requests 404.
No app was restarted. Direct-backend protection still awaits its candidate build.
Angor candidate UI was exercised against the actual dev Mempool stack in a
throwaway gateway: desktop/mobile rendered, zero failed JS/CSS assets, one
WebSocket connection each. The gateway was removed afterward; this is candidate
integration evidence, not a published or permanently installed app update.
### Same-node NPM networking correction
Read-only inspection of the production NPM namespace reproduced HTTP 502 for its
own configured indexer route. Host requests to the LAN upstream returned 200;
requests from the existing pasta namespace to that same LAN address were refused.
A disposable container on the proposed `slirp4netns:allow_host_loopback=true`
network returned 200 for both the LAN upstream and `host.containers.internal`.
No production NPM/nginx configuration or container was changed in this check.
The candidate now declares this network in the manifest and first-boot path,
with explicit Quadlet/API support and legacy drift detection. The Podman API
`network_options` shape was checked against `podman generate spec` locally.
The real NPM integration fixture now uses the proposed network and a LAN-bound
same-node upstream, rather than placing both fixtures on one custom bridge.
Flat-layout integration passed namespace reachability, host routing, verified
TLS/WSS, ACME file access, certificate replacement/reload, custom routes, password
and IP ACLs, spoof rejection, host lifecycle and NPM restart with preserved DB.
The earlier loopback-only fixture failed because this machine resolves the host
alias to its LAN address; its bind was corrected before repeating the test.
The latest isolated nginx guard test passed 120 public IPv4/IPv6 negative cases
plus private access, ACME, proxy-marker rejection and reload. Python guard/bridge
regressions passed 23 tests, including exact emergency-route retirement, failed
migration rollback and preserving operator-modified routes. Backend compilation
and new direct-listener tests are still pending. Required public staging renewal,
actual upgrade/reboot, yaya and exact OTA/ISO acceptance remain open.
### Active nginx site layout regression
The dev node has a regular `sites-enabled/archipelago` file, not a symlink to
`sites-available`. Both the guard and ACME resolver now select the active file.
Unit coverage verifies copied sites and symlink targets, preserving inactive
operator copies and the links themselves. Nginx configuration backups must not
be created inside `sites-enabled`, whose wildcard include would load them.
The active guard was applied on dev, with private HTTP 200 and public-ingress
marker 404 verified after reload. Shorty remains untouched. Do not count the
initial inactive-file edit as a security deployment pass.
### LoRa flasher added to release gates
Both dev and Framework lack the esptool executable and Python module. The
backend invokes a bare `esptool` and retries even process-spawn failures. The
shell updater installs it opportunistically, but the OTA runtime tool list
omits it. Candidate packaging adds a pinned self-contained `archy-esptool`
with its ESP32-S3 stub to mandatory OTA/ISO payloads. Candidate preflight runs
before stopping the radio; retries are limited to recognized serial transport
failures. Concurrent flash registration now uses one exclusive lock.
CP2102 USB identity does not uniquely identify a Heltec V3. The candidate removes
that unsafe inference from backend and UI and requires explicit board selection.
Actual board models were requested before firmware writes. Dev exposes one
CP2102 serial radio. Framework SSH works but currently exposes no mesh-radio,
ttyUSB or ttyACM port. No radio has been erased or flashed in this investigation.
Physical MeshCore UK acceptance on both nodes remains required and pending.
Dev connection diagnosis: the failed flash stopped its listener before spawn
failed and left the enabled setting true. A read-only protocol probe identifies
the existing radio as Reticulum/RNode. An explicit listener disable/enable restored
`device_connected: true` on `/dev/mesh-radio`, without flashing or native-service
restarts. Candidate configure logic now compares desired enabled state with the
actual listener task, including stopped/finished handles; same-settings reconnect
is covered by a new isolated regression. Probe/configure and flash registration
are coordinated to prevent concurrent serial owners.
The packaged `archy-esptool` build passes in a clean environment, including loading
the actual ESP32-S3 stub through esptool's own loader. It is installed and self-tested
on dev and Framework; a compatibility command supports their current backends.
This verifies tooling availability, not physical flashing. Framework's USB sysfs
inventory shows its hub/storage/network/keyboard/display devices but no serial
radio. Board confirmation and Framework radio detection remain pending.
Additional Podman API acceptance: a disposable API service created a container
with the candidate `netns`/`network_options` payload. Its effective generated
specification preserves `allow_host_loopback=true`. The normal inspect network
mode omits options for API-created containers, unlike the CLI-created case;
candidate drift detection now consults the effective specification before
recreating such a container. Added a regression against repeated recreation.
The probe container and temporary API service were removed. The real isolated
nftables tunnel regression also passed (NPM peer port and LND remain separate).
### Latest acceptance checkpoint: radio connection and release status
The complete frontend suite passed: 143 files, 1,159 tests. Type checking and
both new radio setup tests also passed. The final isolated backend build/test
run is still pending; the previous run exposed an NPM/Router port collision,
which was corrected by assigning NPM's local HTTP listener port 8088. Do not
report the previous run as fully passing or the final run as completed.
Yaya's identity has been confirmed. Its existing managed web-tunnel drop-in
clears manifest port publications and supplies private tunnel HTTP/HTTPS ports
plus the local admin port. This would suppress the candidate bridge's new
loopback HTTP/TLS listeners. Migration must preserve the working tunnel/site,
add the required local listeners, validate the managed firewall/lifecycle,
retain custom overrides, and cover repeat upgrade and rollback. The current
bridge rejects non-loopback listeners, so the supported tunnel topology also
needs explicit qualification. No tunnel or NPM runtime change was applied to
yaya during this diagnosis. Its management source guard was applied and tested:
private dashboard HTTP 200, public-ingress-marked request 404.
Dev radio connection has been restored on its existing Reticulum firmware.
Framework still does not enumerate a USB serial radio. Both nodes now have the
self-tested packaged flasher, but physical MeshCore UK flashing, post-flash
handshake and reconnect acceptance remain open pending board identification and
Framework USB detection. No device firmware has been written.
OTA, app catalog and raw ISO publication remain held. Outstanding acceptance
includes NPM migration/renewal/reboot and exact artifacts, end-to-end delivery
of the reported paid file, physical companion uploads, full Angor discovery
(the 34 missing original announcements), radio hardware tests, and the final
dev/yaya candidate deployment checks. Retained tasks above remain in scope.
### Dev Heltec V3 physical flashing result
Full 8 MiB pre-flash backup saved privately with mode 0600 and checksum. After
removing the confirmed stale radio sidecar, the exclusive read completed.
The normal mesh.flash-device RPC then flashed the official Heltec V3 Companion
USB v1.17.1-d929643 merged image successfully (100%, no error). The image's
size and SHA-256 were checked against the official GitHub release metadata.
Independent serial protocol queries confirmed model Heltec V3, firmware
v1.17.1-d929643 and actual RF readback: 869618 kHz, 62500 Hz bandwidth, SF8,
CR8 (EU/UK Narrow). This is device readback, not merely saved host settings.
The listener was then re-enabled and reported connected as meshcore. No wallet
or native Bitcoin/LND service restart was used. MeshCore remote reboot is not
supported by the current API; that attempted check returned an explicit error.
Physical unplug/replug and communication to Framework remain pending.
Live qualification additionally found incorrect binary DEVICE_INFO/SELF_INFO
parsing and a stale host-side RF-applied marker after full-chip flashing.
Candidate changes decode the current official binary layout, query the actual
firmware version during initialization, and invalidate the RF marker after a
successful flash. The dev marker was backed up and cleared before provisioning;
the independent readback above confirms settings applied. New parser, startup
cancellation and marker lifecycle regressions are queued/running; the prior
1,647 passing tests do not cover these later changes.
Framework's V4 official USB image has been downloaded and verified. Despite the
operator confirming it is plugged in, repeated sysfs/device checks show no
ESP32 USB or serial port. USER/BOOT plus RST bootloader entry was requested;
Framework has NOT been flashed and the two-device acceptance remains open.
### Operator deferral and latest qualification
Operator explicitly deferred Framework radio/hardware work and instructed us to
continue all other release tasks. Framework V4 flashing, USB reconnect and
radio-to-radio acceptance remain UNVERIFIED / OPERATOR-DEFERRED; this is not a
pass. Do not request further Framework radio operations unless needed and the
operator resumes that work. Dev V3 acceptance and durable fleet fixes remain.
The final radio backend suite passed 1,650 tests, zero failed, four ignored,
including sidecar-startup cancellation, current MeshCore metadata parsing, and
post-flash RF-marker invalidation. Frontend baseline remains 1,159 passed.
Correction to the earlier yaya tunnel concern: direct inspection of the active
Quadlet and all drop-ins confirms web-tunnel.conf ADDS private tunnel ports; it
does not contain an empty PublishPort reset. The earlier statement that it
cleared manifest listeners was incorrect. The new loopback publications therefore
coexist declaratively without editing that working tunnel drop-in. The bridge
validator now permits only the known HTTP/TLS tunnel ports bound to a currently
assigned RFC1918 address on an actual WireGuard interface named wg-web; it still
requires a separate loopback upstream, and rejects wildcard/public/unassigned
bindings and any admin-port exception. Python bridge/guard tests: 27 passed.
Actual yaya candidate upgrade and public route acceptance remain pending.
### NPM public certificate and restart qualification checkpoint
- Main backend: 1,651 passed, zero failed, four explicitly ignored hardware /
external integration tests. Container runtime library: 80 passed, zero failed.
- Bridge/management guard Python suite: 27 passed. Shell syntax and actual ISO
overlay-content test passed.
- Candidate validator inspected yaya's real runtime/WireGuard interface and
accepted its existing web tunnel publications while selecting proposed
loopback HTTP/TLS upstreams. This was read-only, not a runtime upgrade.
- Existing yaya public HTTP ACME route returned the exact random token body
written inside NPM. Lets Encrypt STAGING initial issuance and renewal dry run
succeeded using separate temporary account/config/work/log storage. Current
production certificate and host records were not replaced. Public site HTTP
and trusted HTTPS retain their authentication requirement (401).
- First renewal harness timed out while Certbot used a 292.7-second randomized
delay; the remote log confirmed successful simulated renewal. A deterministic
rerun with --no-random-sleep-on-renew returned exit 0 and success confirmation.
Only the temporary staging directory was removed afterward.
- Real disposable NPM nested-layout test completed: namespace LAN upstream,
API host creation, custom locations, client-IP spoof rejection, exact ACME
token, trusted TLS/WSS, certificate replacement, password/network ACLs,
enable/disable/delete, and restart with retained DB. Latest restart took 7.6s.
Earlier rerun exceeded the fixture's 90-second restart window; the test now
uses the manifest's 180-second budget and records both route/admin statuses
and container state on failure. Do not erase that earlier observed failure.
- Cleanup was hardened to continue cleaning other fixtures after a timeout.
Two early test runs passed functional assertions but failed cleanup; their
leftover disposable containers/networks were explicitly removed. The latest
full run exited successfully.
Legacy non-Quadlet repair now retains the old container for rollback, restores
it after replacement failure, preserves its exact image and environment values,
and waits for HTTP API readiness. Environment values use an exclusive mode0600
file cleaned on drop, not argv or the host process environment. Invalid/multiline
entries fail before stopping the original. An occupied rollback slot is preserved
for review rather than deleting an unknown container. Live interrupted-migration,
additional operator-override and rollback acceptance remain OPEN; unit success
is not proof of those deployment paths.
The deployment backend and frontend build are in progress. Full candidate dev/
yaya upgrade acceptance, reboot, exact signed OTA/catalog and booted raw ISO
remain open. Framework radio is operator-deferred, not passed. The original paid
file bytes, physical companion upload and 34 missing Angor announcements remain
separately tracked.
### Further completed acceptance
The complete disposable NPM test now includes a deliberately failed replacement
with an occupied host port. Restoring the retained container preserved its exact
container ID, database, configured hosts and authenticated API access; the test
exited successfully and cleaned its fixtures. This verifies the Podman rollback
mechanism, not yet the full installed backend's legacy-repair entry point.
Dev frontend build completed and was deployed with a separate rollback backup.
Served production Transactions layout passed at widths 390 and 1440: transparent
background, no image/blur/shadow/border, nowrap and exactly one row. Mobile rail
is 324px wide with 419px scroll content. Backend candidate compilation is still
in progress, so the latest backend changes are not yet deployed.
Dev Bitcoin remains unpruned and in IBD (observed block543676/header969495,
verification progress0.2284). This is not full-chain Angor acceptance. The operator
identified the seller of the failed Lightning purchase as Amish Paradise.
On 2026-10-02 the operator confirmed the other tester received the file and
accepted closure of this individual recovery. Seller access is no longer needed
for that recovery. This does not establish that the candidate fix delivered it;
durable settlement/delivery regression acceptance remains required before
release. No additional payment was made. Earlier references in this document
to missing original purchase bytes are superseded by this operator acceptance.
### Read-only Shorty migration preflight: remaining ownership conflict
Preflight found both flat and nested NPM databases. The live container's explicit
/data mount identifies the active one, so the candidate resolver now uses that
verified mount (or its saved validated receipt after a managed stop), preserves
both databases, and still refuses multiple databases without an authoritative
selection. Python coverage verifies both explicit choices and unchanged bytes.
This helper update occurred after the deployment binary build started; a final
release rebuild must include it. Do not claim the in-progress binary contains it.
After resolving storage, the two Angor emergency routes match the exact known
handoff templates. Another existing file, shop-btcpay.conf, conflicts with an
enabled NPM record: the manual route supplies HTTPS using certificate10, while
the NPM host currently has certificate_id0 and SSL forcing disabled. The manual
route and NPM record cover the same two public names and backend web port. Blindly
retiring the route would break its HTTPS. No database, host, certificate, route
or runtime was changed on Shorty. The bridge correctly refuses this ownership
conflict and now names its configuration file in the diagnostic. Align TLS/route
ownership and verify the public shop before retiring that manual configuration;
Shorty's full migration acceptance remains OPEN. Preserve live containment.
### Candidate deployment and additional real-upgrade ACME regression
The operator explicitly deferred Framework's physical radio investigation and
requested continuation of all other work. Framework radio remains unverified.
Dev and yaya now run the backed-up unpublished backend candidate SHA256
4c47269b3480ca0362df18dae160c073a19ea33507e04cacdad5b96837990ca6 and production
frontend index 3099c4ba44528a4a4c524f9a26159414558efa16abdd12cc7bfd64376cbb6089.
Both management health checks passed; native Bitcoin/LND container identities
and start times were unchanged. Yaya public site retains trusted TLS and its
401 authentication requirement; NPM admin API200, private dashboard200 and
public-ingress-marked dashboard404. The first yaya staging attempt stopped
before binary replacement because rsync was absent; deployment now uses Python
copying without that dependency and completed successfully.
Actual startup exposed an additional regression: the canonical nginx template
had only HTTP ACME, while the bridge demanded two locations. Startup rewrote the
previously repaired config and the bridge rejected it before fixing the nested
root. Source now adds HTTPS ACME to the shipped template and migrates the exact
recognized legacy default-server layout; custom/ambiguous layouts still fail
closed. The missing-token route must return404 rather than the dashboard SPA.
28 Python checks passed. The real isolated nginx suite now starts from the
legacy missing-HTTPS layout, applies the migration, and passes all120 public
negative cases plus HTTP/TLS exact-token, private-access and reload checks.
Applied the latest helper and its atomic ACME-only repair to yaya: actual token
written inside NPM returned exact200 over host HTTP, host HTTPS and public HTTP;
missing tokens returned404 for allthree. Public site trustedTLS/auth preserved.
Local self-signed host HTTPS was tested with certificate verification disabled;
public site HTTPS used normal certificate verification. Shorty was not modified.
The running backend still embeds the older helper/template; final rebuild is
REQUIRED before restart/reboot/persistent upgrade acceptance can pass.
The prepared unsigned catalog validates with zero metadata drift and trusted
registry hosts. Its only changed entries are NPM and Angor indexer1.0.2. It has
not been signed, installed or published. Yaya's current signed catalog retains
NPM's old pasta network/tunnel-only HTTP+TLS listeners; full NPM runtime/bridge
migration acceptance awaits the reviewed signed catalog. Do not mistake the
backend/UI deployment or ACME-only fix for completed catalog migration.
### 2026-10-02: rebuilt candidate deployed; private catalog qualification prepared
Release-profile candidate build completed successfully. SHA256:
af0648ad4ef8b6183d3c1ff485721fa40b12bb730c6e0322bc5f209ed06fce39.
Focused bootstrap tests:10 passed. Full isolated backend rerun:1651 passed,
zero failed, four explicit hardware/external ignores. Python guard/bridge28
passed again. No new source changes occurred between these checks and deployment.
Deployed this rebuilt backend on dev and yaya, with private previous-binary,
nginx and native-container baselines. Both manager health checks passed. A later
post-startup comparison confirmed Bitcoin/LND identities/start times unchanged.
The installed bridge helper now matches latest source bytes after restart.
Private UI200, marked-public HTTP/HTTPS404 and missing HTTPS challenge404 passed.
Dev HTTPS intentionally binds its LAN/WireGuard addresses, not127.0.0.1; an
initial loopback probe got connection refused, corrected to the actual listener.
This was a test-address error, not a product outage. Local self-signed HTTPS
checks skip certificate verification; public-site TLS checks use normal trust.
Full-machine reboot qualification is still pending.
Prepared a fresh candidate catalog with only NPM and Angor indexer entries changed.
Metadata drift0; registry trust check passed. Unsigned SHA256:
5801309bf21d3f6fd03ce5702d68b383a518f734092bf265f5e0ad243095a25e.
NPM's new manifest is capability-gated by runtime-migration-backup-v1; older
nodes retain the original manifest. This candidate is for private qualification,
not fleet publication. An operator-only hidden-input signer validates the exact
catalog and binary hashes, checks the pinned release root and restores the
unsigned original on failure. Its noninteractive refusal was tested. Signature
is required before testing through the nodes' normal trusted-catalog path.
No catalog, app image, OTA or ISO was published. Framework remains deferred;
all other open requirements retain their previous status.
### Signed catalog and private qualification selector
The operator signed the qualification catalog. Cryptographic release-root
verification passed locally and on yaya; after removing signature envelope fields,
its contents exactly match the reviewed unsigned candidate. No publication.
The catalog is staged under /var/lib/archipelago/qualification on both test nodes,
with previous catalog/app metadata and container identities privately backed up.
Normal mirror loading deliberately forces the public origin first, so simply
prepending a private mirror cannot reliably test an unpublished candidate.
Implemented ARCHY_APP_CATALOG_CANDIDATE as an explicit absolute-file selection:
requires an anchored release-root signature, validates before cache replacement,
retains exact signed bytes, does not alter mirrors/trust, and fails without
public fallback when the selected file is invalid. Added unsigned, tampered,
wrong-key, malformed, missing, oversized, relative-path, valid and idempotent
coverage. Full isolated backend suite:1653 passed,0 failed,4 explicit ignores.
The optimized selector build is still in progress; selection is not enabled yet.
See docs/candidate-catalog-qualification.md for activation and mandatory removal
once the tested public catalog is available. Do not leave test nodes pinned.
Yaya NPM preflight:8088/8444 are free, active public host has no conflicting
host-nginx ownership, database tables and certificate-file hashes saved privately.
No Shorty mutation. Dev public Angor reference acceptance passed TLS/WSS, exact
funding commitment, official Explore and detail/statistics again; this still
checks only the known original project, not all35. Dev Bitcoin continues syncing
(reported sync_progress approximately0.307); full-chain acceptance remains open.
Current tested hardware product codes:dev20CLS7S900 and yaya20CLS6BH00, both Podman
5.4.2; kernels6.12.74+deb13+1-amd64 and6.12.107+deb13-amd64 respectively. Framework
remains deferred. No Docker or new ISO-boot acceptance is implied.
### Signed qualification deployment and legacy upstream compatibility
The optimized candidate selector build completed, SHA256
`9cc9271ee1b4f8f13d798193cef97c1e4304a89a240f11f851eb71568bd105e1`.
Both development acceptance nodes now run it with the exact root-verified private
catalog. The isolated backend suite passed 1,653 tests, zero failures, four
explicit ignores. This is unpublished qualification, not a release.
Actual NPM migration exposed an additional regression that the LAN-upstream
fixture missed: a saved site uses pasta's former host gateway `169.254.1.2`.
Default slirp's gateway differs, so the request timed out from inside NPM even
though admin readiness passed. A disposable container verified the same saved
upstream with `slirp4netns:allow_host_loopback=true,cidr=169.254.1.0/24`.
A temporary qualification Quadlet drop-in now selects that network, using an
empty `Network=` reset before the replacement to avoid multiple network modes.
The existing site's trusted public HTTPS authentication response is restored.
Post-repair checks passed: request from NPM's actual namespace; exact saved user,
host, certificate, ACL and settings rows; unchanged certificate bytes; private
migration backup and prior unit; unchanged unrelated container IDs/start times;
retained WireGuard tunnel ports; host bridge completion; private dashboard200,
marked public HTTP/HTTPS404; missing challenge404; exact challenge body from
inside NPM over local HTTP/HTTPS and public HTTP. Native Bitcoin/LND identities
and start times remain unchanged.
**Release blocker:** integrate and test legacy gateway compatibility in all
supported runtime paths and signed manifest, including fresh/upgrade/restart
cases and LAN/host.containers.internal upstreams. The current signed candidate
alone is insufficient. Temporary user-unit drop-in
`nginx-proxy-manager.container.d/90-qualification-host-gateway.conf` must be
removed after the corrected managed configuration is verified. Do not remove
it before then or claim the migration passed without it. Candidate catalog
service selectors also require the cleanup described in
`docs/candidate-catalog-qualification.md` after final publication.
### Development Angor candidate update
The supported `package.update` RPC selected the private signed catalog and
upgraded only `angor-indexer` to the locally built 1.0.2 image. The actual dev
endpoint rendered the Mempool explorer at widths 390 and 1440 with zero failed
JavaScript/CSS requests and one WebSocket connection each. All unrelated dev
containers retained their exact IDs and start times. This verifies the local
explorer presentation, not complete blockchain indexing or recovery of the 34
missing original Angor project announcements. Bitcoin remains in IBD.
The repaired NPM namespace also reached the saved gateway,
`host.containers.internal`, and the node LAN address with the expected site
authentication response. The durable compatibility blocker remains open.
## Live Lightning purchase: Framework to Shorty — 2026-10-02
Operator explicitly authorized a very small new test purchase, then performed
it from Framework. This is separate from recovering the Amish Paradise sale.
Fixture: `archy-lightning-delivery-test-20261002.txt`, price 1 sat, Lightning only.
Read-only checks confirmed one matching seller invoice, SETTLED for exactly
1 sat, and Framework payment SUCCEEDED for 1 sat with 1 sat routing fee
(1,000 msat). Total spent was 2 sats. The assistant sent no payment.
Framework has exactly one durable purchased-content ownership entry for the
fixture, with backend `lightning`, paid_sats=1 and size_bytes=121. Its cached
file SHA256 equals the original seller fixture:
`d55f7a6acd77bdc3c35c65ecac6d1492096e99252d07d433e6286544540cde7e`.
**PASS: actual node-wallet payment, seller settlement, delivered bytes and
persisted buyer ownership/cache.** Framework runs the candidate backend
`8fb6249d1869bb8c9aea26d0f846de5b3eec328113a5c7f573628306e26e652e`;
Shorty runs `e108b78bbbd21cb7d5d47c8d0b7b9b19b63fb0c44678773603202440ec7d6f5b`.
This also exercises the candidate buyer against the existing seller version.
Live reopen without payment and restart acceptance are not established by
this check. Shorty had no matching durable entitlement JSON in the inspected
location; do not attribute the candidate seller persistence implementation to
this older seller binary. No node or wallet was restarted. The tiny fixture
remains available for a free cached reopen check; remove only its catalog
entry/source file afterwards, preserving buyer ownership and payment records.
### Operator-confirmed free reopen — 2026-10-02
After the verified one-sat purchase, the operator reopened the file on Framework
and confirmed it worked without another payment. **PASS: live paid delivery,
durable buyer ownership/cache, and free repeat access**, with independent
settlement/byte checks above and operator confirmation of the reopen UI.
This closes that specific live acceptance check; it does not establish an
untested restart, outage, or seller-upgrade scenario.
The temporary seller catalog entry and source fixture were removed after
acceptance. Buyer purchased bytes/ownership and all payment records were preserved.
+519
View File
@@ -0,0 +1,519 @@
# Archipelago 1.9.0-alpha release acceptance
Status: **OPEN — unpublished.** Operator requires the `-alpha` suffix: final version
`1.9.0-alpha`, tag `v1.9.0-alpha`, and matching OTA/ISO artifact names. Earlier
unsuffixed candidate evidence below is historical, not a final artifact pass.
Operator selected the 1.9.0 series instead of the provisional
1.8.23-alpha. This is the current summary; retain the detailed history and all
requirements in [the regression ledger](post-1.8.22-regressions-20261001.md) and
[the earlier acceptance record](release-1.8.23-acceptance.md). No unexecuted test
is a pass. Provide the operator a node-specific action/expected-result checklist
whenever human acceptance is needed.
## Current evidence
- Latest alpha backend source: isolated suite 1,681 passed, zero failed,
four explicit ignores; separate container runtime suite 82 passed. Optimized
build including the Nostr security and File Browser changes is in progress.
- Frontend: full suite 1,211 passed across 148 files; production UI and AIUI
builds passed. Real dev desktop/mobile upload fault injection passes, including
interrupted JWT refresh and exact saved-file hashes.
- Currently deployed backend on dev/yaya SHA256
`e218e40f5c16c3d0cc4dc06c0a378c14b56b9087ded5c515b8a48351ceea3bcf`.
It includes Nostr/File Browser fixes but predates the alpha version suffix.
Private rollback backups exist.
- Latest deployed UI index SHA256 on dev/yaya
`67de835a25db59a483314eff583b809c3468c8529080bfa74c9962e44a6f54f9`.
Both served byte checks pass; unrelated production containers stayed unchanged.
- NPM corrected gateway/client-IP integration: 23 Python checks and complete
disposable real-image integration passed. Catalog generator now requires both
migration-backup and legacy-gateway capabilities; its generator/drift selection
regression passes. Candidate metadata drift zero and registry trust passed.
- Cuprate/NetBird/BTCPay grouping previously passed actual yaya desktop/mobile,
hard reload and BTCPay category/icon checks. No product installs were performed.
- Real one-sat Lightning purchase, exact bytes, buyer ownership/cache and operator
free reopen passed. Original tester recovery accepted separately.
- Transparent transaction rail, compact origin-screen upload bar/cancellation and
cooperative-close controls have recorded desktop/mobile browser acceptance.
- Framework original LND startup incident is closed with operator acceptance.
## Open release gates
- [ ] **NPM:** corrected private signature, dev/yaya selection and yaya override
retirement now PASS (2026-10-05). Remaining: full boot/OTA/ISO and
staging-CA issuance/renewal and full legacy-backend migration/rollback
acceptance; retain the completed
fresh/nested disposable and actual yaya state-preservation checks.
- [ ] **Shorty NPM:** shop certificate12/Force SSL are operator accepted and
independently verified; qualify and apply the manual-route migration. Preserve live
management containment and current public app routing.
- [ ] **Security:** verify final deployed/booted artifacts against public raw IP,
unknown Host/SNI, forged forwarding headers, IPv4/IPv6, assets/RPC/WS;
preserve private access, ACME issuance/renewal and public app TLS/WSS.
- [ ] **Fees/Bump:** deployed dev/yaya Fast UI and real isolated funded regtest
(CPFP/RBF, fee history, restart, confirmation/reorg) pass. Authenticated
Framework read-only quote/status acceptance remains. Preserve approved green UI.
No production spending or channel closure is authorized by this checklist.
- [ ] **Paid files:** finish buyer restart/outage and updated-seller persistence
acceptance; preserve atomic ownership and safe retries without repayment.
- [ ] **Uploads:** prior physical companion flow is operator accepted. New
resumable-transfer requirement needs interrupted-network/background
recovery acceptance; viewport checks alone are not physical-phone proof.
- [ ] **File Browser credentials:** unique managed login, default-password
removal, account/file preservation and rollback pass real Podman fixtures
including actual Quadlet restart. Deploy/verify dev and yaya, rerun yaya
upload tests, qualify Framework's reported auth issue, and verify packaged
OTA/ISO startup. Docker behavior is not inferred from Podman fixtures.
- [ ] **Apps:** complete upgrade inventory matrix for installed/stopped/removed/
restarting/legacy aliases; Immich/retired-app removal and unexpected-service
identification; Portainer/Gitea migration from actual request namespace.
- [x] **UI:** category-view clear-search control passes on served dev/yaya UI
at390/1440px: click and Escape clear the field, retain focus and stay inside
the existing field. `/tmp/archy-190-final-search-live.log`. Earlier grouping
and transaction-rail results are retained.
- [ ] **Angor:** dev full-chain acceptance after unpruned Bitcoin sync; retain
all-project discovery requirement and 34 unrecovered original announcements.
Publish tested explorer/API app update and optional relay in signed catalog.
- [ ] **Post-release demo deployment:** operator requests updating the existing
public software demo at https://demo.archipelago-foundation.org/ through its
established Portainer/Gitea workflow after release. Inspect the exact
stack/source, preserve rollback, verify served 1.9.0-alpha and demo flows.
This is not the Yaya v4v website or a Portainer version upgrade.
- [ ] **Final artifacts:** finish versioned build; exact candidate deployment;
OTA update/rollback and raw ISO boot/install; signature/checksum validation;
publish Git/ngit, app images/catalog and artifacts; verify public downloads
and fleet discovery; remove temporary catalog selectors after publication;
supply LAN SCP command for the raw ISO.
## Retained regression scope
Mempool version/update clearing/deduplication; Minibits and Cashu same-mint payment
handling; LND startup/Receive/unknown balances; Bitcoin warmup and IBD dashboards;
pruning and X250 kiosk picker; AIUI background; launch readiness/card geometry;
GitWorkshop; Gitea/Portainer; safe network diagnostics; operator uninstall/stop
choices; companion images and generated service configuration; radio payload and
UK MeshCore dev V3 acceptance; previously reviewed/merged PRs. Detailed original
requirements and evidence remain in the linked ledger, not silently dropped.
## Explicit boundaries
Framework V4 radio is now reported working by the operator (2026-10-05).
No reflash is requested; retain this as operator evidence, separate from automated
hardware coverage. Previously
accepted Primal comment and lost-response Cashu receipt follow-ups remain separate.
Only one Angor project has full public browser acceptance; 34 missing announcements
are not proven globally lost. Do not claim complete recovery from one fixture.
### Further live evidence
Framework's existing one-sat purchased-file ownership entry and exact 121-byte
cache remain present after the Bump management restart. Purchase timestamp
09:15:03 UTC precedes manager start 10:42:52 UTC on 2026-10-02. SHA256 remains
`d55f7a6acd77bdc3c35c65ecac6d1492096e99252d07d433e6286544540cde7e`.
This establishes buyer persisted bytes/ownership across that actual manager
restart. It does not establish a full-machine reboot or seller outage scenario.
No payment or restart was performed for this read-only check.
Yaya post-deployment checks pass: native Bitcoin/LND unchanged, private UI200,
marked public HTTP/HTTPS404, missing HTTPS challenge404, exact challenge bytes
written inside NPM over local HTTP/HTTPS and public HTTP, existing public site
trusted HTTPS/authentication preserved. This is not yet the new signed-catalog
migration without the temporary network override.
### Versioned build and final suites
The optimized 1.9.0 backend build passed; SHA256
`e1b94e6de9b5cc3dfcec16994bc3d0f710f3b7bcc6e5af045c6e53bb94b6abf0`.
The final frontend suite passed **1,187 tests in 146 files**, zero failed.
All 48 script unit tests passed, as did app build-context, manifest-shell,
ISO overlay, network-doctor, pruning and LND UI readiness checks. The release
harness now includes NPM bridge, guard, catalog capability and isolated actual
nginx security tests. All 120 public-network rejection cases passed again.
Yaya category search clearing passes desktop/mobile: click, Escape, focus and
contained icon, unchanged 40/52px field heights. Portainer's actual namespace
still reads Git smart HTTP refs and Compose from the expected branch; native
services and the production site were not changed by those probes.
Fresh Angor relay queries still recover only one of the 35 original signed
announcements. Eight relays returned results/EOSE; two archive endpoints were
unavailable. A release-scope decision was requested rather than silently waiving
this external-data requirement. The reference HTTP endpoint was readable through
Python, while the Node HTTP client received HTML; relay queries used the recorded
35 exact event IDs, and accepted only matching validly signed kind3030 events.
A new isolated runtime harness executes the production backend against actual
Bitcoin/LND regtest processes, with private process/network/filesystem namespaces,
normal account setup/login and disposable wallets. Its CPFP, child RBF, recipient,
fee-budget, duplicate-submit and backend-restart checks passed. Confirmation and reorg recovery also passed after the fixture announced a
competing empty block. The earlier disconnect-only fixture failed to notify the
expected new chain state and is retained as a failed attempt. Full run evidence:
`/tmp/archy-fee-regtest-run3.log`. No production wallets or funds were used.
### Current deployment and final history correction
The versioned backend `e1b94e6de9b5cc3dfcec16994bc3d0f710f3b7bcc6e5af045c6e53bb94b6abf0`
and the production UI are deployed on dev and yaya. Manager health200, served
index byte match and unchanged unrelated container IDs/start times passed on
both. Private rollback directories are `support/190-versioned-20261002`.
Actual category search clearing passes desktop/mobile on both nodes.
A final source audit found fee-only child history grouping was still absent.
The correction is now implemented with conservative receipt/ownership/input/
fee-only/current-chain verification, replacement-aware totals, linked fee
history and current-child Bump targeting. Nine focused UI tests and the new
production dashboard build passed. This correction is NOT in the deployed
backend above. Its isolated backend suite and extended actual regtest acceptance
remain in progress. The concurrent optimized compile was deliberately stopped
to reduce build contention and must be restarted after isolated compilation.
Corrected NPM candidate remains unsigned. The operator was given the exact
private signing command and asked for the affected physical companion route.
No publication or release-scope waiver is inferred from silence.
### Payment audit follow-up
Found a separate older Cashu repeat-download fallback that allowed a new spend
when an ownership record existed but its cached bytes were missing; an unreadable
index was also treated as empty. The payment guard now reads ownership strictly
and returns a recovery error before mint/spend in either case. Successful cache
hits retain the zero-payment response and same-seller filename alias handling.
The new regression exercises first purchase, exact/alias cache hits, different
seller, missing bytes and damaged index preservation. Final suite/rebuild are
running; no live wallet was modified. Previously documented lost-response ecash
receipt limitations remain separate from this correction.
Framework read-only optional Files-copy verification could not proceed because
the SSH control connection expired and BatchMode login was rejected. Existing
buyer cache/restart evidence remains valid; no password or account was changed.
Actual served Fast-send controls pass on dev/yaya at390/1440px: initial Fast,
explicit Standard selection and reopen reset to Fast. No spending RPC submitted.
Two earlier harness attempts had ambiguous Close/Send locators during modal
transitions; the corrected final run passes all four cases. This is send-form
acceptance, not a real cooperative-close transaction or omitted-fee wallet spend.
Final isolated suite after fee-history and missing-cache payment corrections:
**1,668 passed, zero failed, four explicit hardware/external ignores**. The
optimized build and extended real-regtest run are chained in
`/tmp/archy-190-complete-validation.py`; log
`/tmp/archy-190-complete-validation.log`. They have not yet completed.
The packaged radio flasher self-test also passes (`archy-esptool4.8.1`,
ESP32-S3 stub ready); this does not change Framework radio deferral.
## Signed qualification completed — 2026-10-05
Operator confirmed signing; exact private catalog verifies against the pinned
release root. Final optimized backend SHA256
`cfddec834a53609f8bef924f3905da76df45f22426cac2628c4c2cb06bea5d09`
and final dashboard index SHA256
`4b8f6ceb4ebe1e3b8ce1a0786f3e8a9d38e6d42ba174bf64bd54f4b23d7c13ff`
are now deployed on dev and yaya. Both health checks, served byte matches and
unrelated container identity/start-time checks passed. Root-only rollback
directories: `support/190-final-20261005-20261002` (literal generated name).
Both cached catalogs exactly match the new signed candidate.
The optimized actual Bitcoin/LND regtest passed with the new history assertions:
CPFP, child replacement, unchanged recipient, bounded fee, duplicate submission,
one payment with replacement-aware fee history, backend restart, confirmation
and reorg. No production funds were spent. Log: `/tmp/archy-fee-regtest-run4.log`.
Yaya selected the managed legacy-compatible gateway from the signed variant.
The temporary `90-qualification-host-gateway.conf` was backed up and removed
only after inspecting the generated managed network. NPM restarted successfully.
Complete selected DB tables and certificate bytes match the private baseline;
loopback and existing tunnel publications remain intact, admin API is healthy,
and an actual NPM-namespace upstream request returns the expected authenticated
site response. A private managed migration archive exists.
A subsequent manager restart and120 seconds of repeated reconciliation retained
all container identities/start times and did not recreate the removed override.
Migration checks passed again. Logs: `/tmp/archy-190-npm-override-retirement.log`
and `/tmp/archy-190-npm-persistence.log`. This is not full-machine reboot evidence.
Post-migration public integration passes: exact challenge bytes from NPM on
local HTTP/HTTPS and public HTTP, missing HTTPS challenge404, private UI200,
public-marked management HTTP/HTTPS404, public application trusted TLS and
authentication retained. Portainer's actual namespace reads Git refs and Compose
at verified tip `3ae171d6b0c728665a860520fe393c0abb772798`. Native Bitcoin/LND
unchanged. Deployed Fast-default/reopen/slower-select browser checks pass on
both nodes at390/1440px, without submitting transactions.
Additional external IPv4 probes from Shorty passed24 raw-IP/unknown/forged-host
cases with forged forwarding headers and root/RPC/assets/WebSocket paths.
Important boundary: the public front gateway returns its static Default Site
for unknown HTTP roots, rejects assets/RPC/WS with400/404, and rejects unknown
TLS names during handshake. Those are not dashboard responses. The first
harness required404 everywhere and failed on that public Default Site; retained
logs record the corrected interpretation. These probes validate the deployed
public gateway path, not direct WAN access to the node nginx. External IPv6
remains unverified; prior isolated IPv4/IPv6 guard tests remain separate.
No Shorty nginx/NPM configuration was changed.
Remaining operator inputs: normal Shorty NPM shop SSL ownership correction
(existing admin login unavailable), affected physical companion upload route,
and the retained Angor34-announcement recovery/release-scope requirement.
OTA/catalog publication, final ISO build/boot and fleet discovery remain held.
Read-only dev chain check2026-10-05: unpruned Bitcoin at830743/970017, verification progress0.63846, IBD true, warnings empty. Full-chain Angor acceptance remains pending sync; no service or wallet change made.
## Operator checks accepted; upload UX amendment — 2026-10-05
Operator reports the requested human checks worked perfectly: Shorty shop SSL,
physical upload flow and Framework dashboard/purchased-file checks. This is
operator acceptance, not a claim of newly independent device testing. Read-only
Shorty verification confirms shop certificate_id12 and Force SSL enabled.
Remaining migration/artifact/security and Angor requirements still apply.
Operator supersedes the globally persistent upload-bar requirement: keep the
bar only on the screen where the batch originated, continue transfers across
navigation, show explicit Complete on successful server save, and use a
completion notification elsewhere. Source now retains the originating route,
removes the global floating bar, keeps the original44px inline bar, and reports
success/error/cancellation distinctly.25 focused store/component/notification
tests pass. The subsequent full frontend suite passed1,193 tests; production
build and actual served desktop/mobile real-upload checks passed. Deployed to
dev/yaya with index SHA256
`86bb728017b118d8e98f032419e7fbfd6ecd78b7e464c982a2075cc38c582814`;
no apps or backend services restarted. Retain this as the preceding UI evidence,
not evidence for the later resumable-upload implementation. No new payment was requested or performed.
### Resumable upload addition — 2026-10-05
Operator requests recovery after a background pause or connection loss. The
installed File Browser identifies as2.63.23/e8a388f8 and supports TUS. Cloud now
has a candidate chunked upload implementation: random same-folder staging path,
server-offset reconciliation, transient retry/online/visibility recovery,
cancellation, final SHA256 verification and rename. Lost final chunk/rename
responses are reconciled without restarting or accepting a same-size old file.
The original-screen-only44px bar, Complete label and off-screen notification
remain. Fifteen focused protocol tests pass; full build/deployed fault injection
are in progress. This is not yet live acceptance.
Recovery requires the selected File to remain available in the running page.
An OS-killed app or expired server upload session may require reselecting the
file. Do not promise uninterrupted background execution or restart persistence.
This gate is additional to the already accepted physical upload flow.
## ngit PR integration — 2026-10-05
Both requested proposals are merged and pushed to Gitea and ngit main at
`2c1bcacf`; ngit independently reports both as `applied`.
- `494d2483`: opt-in NODE_IDENTITY_PUBKEYS for app owner allow-lists. Review
corrected ECMAScript/Rust whitespace differences and added strict public-key
validation. Appliance identity excluded; no private keys or signing capability
given to apps. Existing manifests and the native signing flow are unchanged.
Documentation explicitly describes linking all offered user identities.
- `c18ebd7f`: nostr0.44.7 and nostr-relay-pool0.44.3. The standalone relay pool's
maintenance advisory remains; SDK0.45 migration is a separate follow-up.
- Combined isolated backend suite:1,678 passed, zero failed,4 explicit ignores.
Real loopback hostile-relay test rejects altered content, author and signature
reusing a known DB event ID while accepting a valid event. NIP04/NIP44 normal
encryption and hostile/oversized payload tests pass. The initial relay harness
returned before connection establishment; corrected to wait for an actual
connection before fetch, and the complete rerun passes.
- Evidence: /tmp/archy-190-ngit-complete-tests.log, origin/ngit push logs and
/tmp/archy-190-ngit-postmerge.json. This is source publication, not OTA/ISO or
catalog publication. Later File Browser credential changes need a new suite.
## File Browser secure automatic login — NEW REQUIRED GATE
Operator requests unique per-node credentials, working Cloud from first launch,
no admin/admin and fleet-wide testing. Framework's reported authentication issue
recovered, which is not proof that this gate is fixed. Yaya rejects the saved
password with403 despite healthy File Browser2.63.23. Never count that as a
passed upload test.
Confirmed source issues: first-boot paths still try noauth/admin defaults; the
post-install hook assumes admin/admin and uses an incompatible password-change
request shape; the generated ISO path updates a running DB and uses a different
DB filename; Cloud hardcodes admin and invents admin/admin on missing secrets.
Candidate scripts/filebrowser-credentials.py now provisions a random username
and256-bit password offline with the pinned app image, backs up the selected
DB/config, preserves custom accounts, tests automatic login plus folder access
in a network-isolated container, rejects unauthenticated access, rotates only a
proven admin/admin login, and atomically publishes a0600 credential record.
Fresh real-image acceptance passes. Legacy/default/custom/restart/rollback,
first-boot/Quadlet/runtime wiring, live yaya/dev/Framework qualification and final
artifacts remain OPEN. No live File Browser account or DB has been modified.
Upload resume: source/build/full frontend1,208 tests passed; subsequent48 focused
protocol/client tests passed after filename escaping correction. UI deployed on
dev/yaya index SHA256
`31ac7bcc704c18f88a8b9800fb46bc7941651983e1a99b97d036a8d9e95a58b5`.
Actual dev1440/390px real-server fault injection passed partial offset123456,
offline reconnect, lost final PATCH and rename replies, exactSHA256, encoded
filenames, original-screen-only44px bar, notification, cancel and empty files.
Yaya is blocked at the credential gate above. Physical suspended/killed-app
acceptance is not inferred from these viewport tests.
## 2026-10-05 resumed release qualification
- Latest full frontend: 1,210 tests passed across 148 files. Production Cloud UI
and AIUI builds passed. Dev and yaya serve index SHA256
`3e10a25db75e4712310eb34c98bf7595ad5db3a444f9126a73715b1d40493a33`;
UI archive SHA256 `586d1864c5c4027086194f6b5951a9b770c4e7ce9ba9ec3128e2ac0c1bde55e7`.
Private UI backups: `/var/lib/archipelago/support/cloud-auth-20261005`.
- Real dev browser upload tests pass at 1440/390px, including interrupted JWT
refresh, partial write, offline recovery, lost final PATCH/rename responses,
exact SHA256, encoded filenames, cancellation, empty file, origin-only 44px
bar and completion notification. Initial run overlapped UI deployment and
failed navigation/bar timing; kept as failed evidence. Clean rerun explicitly
verifies successful navigation and passes both viewports. Physical OS suspension
and yaya authentication/upload acceptance remain separate gates.
- Real File Browser image matrix passed fresh, legacy-default, legacy-custom,
legacy-noauth and forced-failure exact DB rollback. Existing file bytes and
user IDs/permissions preserved; custom credentials preserved; admin/admin and
anonymous access rejected. Actual disposable Quadlet pre-start and restart
also pass, with stable managed credentials. Four Python unit tests pass.
- File Browser startup integration now covers the direct runtime, Quadlet,
first boot and ISO script. Binary bootstrap installs its matching helper before
reconciliation. Fixed bundled first-boot missing NET_BIND_SERVICE and duplicate
creation attempt for a stopped File Browser. Live credential migration is still
pending the optimized backend build; no production DB/account modified yet.
- Final combined isolated backend suite: 1,681 passed, zero failed, four ignored.
An earlier run failed the Nostr relay fixture after a normal ping closed its
text-only receive loop. Fixed the fixture to answer pings; the complete rerun
passes. No failed run is counted as acceptance.
- NPM: 23 Python tests pass, including exact emergency BTCPay route recognition,
operator edit preservation, missing certificate/alias refusal and transactional
rollback. Existing emergency Angor routes now also require complete TLS
replacements before retirement. Actual disposable flat-layout NPM integration
passed namespace reachability, legacy gateway, ACME exact bytes, forced HTTPS,
WSS, certificate replacement, password/network ACLs and forged-header rejection,
restart, disable/delete, and forced bind-failure restoration. This is not a
staging-CA issuance/renewal or ISO/reboot pass.
- Shorty read-only inspection confirms shop certificate12 and Force SSL with both
hostname aliases; old manual shop route still uses certificate10. No live
Shorty routing change in this qualification. Migration remains pending.
- Evidence logs: `/tmp/archy-190-final-combined-backend.log`,
`/tmp/archy-190-cloud-auth-ui-dev-live-2.log`,
`/tmp/archy-190-filebrowser-final-integration.log`,
`/tmp/archy-190-filebrowser-quadlet.log`,
`/tmp/archy-190-npm-final-integration.log`.
- OTA/catalog/raw ISO publication remains held. Framework radio deferred;
Angor 34 unrecovered original announcements and dev full-chain acceptance
remain open. README alpha/funds notice is separately published to both remotes.
Additional qualification: real nested-layout NPM integration passed the same
namespace/ACME/TLS/WSS/access-control/restart/rollback matrix as flat layout
(`/tmp/archy-190-npm-final-nested-integration.log`). Container crate isolated
suite: 82 passed, zero failed. Corrected Nostr hostile-relay test passed a separate
isolated repeat (`/tmp/archy-190-nostr-relay-repeat.log`). Dev Bitcoin read-only
status: height832232 of970036, verification0.641006, IBDtrue, prunedfalse. Full-chain
Angor acceptance therefore remains blocked on synchronization, not passed.
## Live File Browser ownership regression — publication hold
2026-10-05 dev candidate backend SHA256
`3e01da72fcea0a61852f3d9038e67630e328c65d6433da749671d60b91c37ffa`
built successfully, then failed live credential migration before DB mutation.
The helper could not create its private backup under the legacy data-directory
owner (host UID100000). The original real-image fixtures aligned data ownership
to the image UID and therefore missed the shipped manifest's different mapping.
The managed File Browser has DAC_OVERRIDE for that layout; the helper did not.
Restored prior backend SHA256
`cfddec834a53609f8bef924f3905da76df45f22426cac2628c4c2cb06bea5d09`
and original File Browser Quadlet with the staged rollback script. Both services
are active. Yaya backend was not changed. No candidate credential record was
published; failed setup stopped at backup-directory creation before DB changes.
Source helper now includes the managed server's DAC_OVERRIDE storage capability;
new real-image legacy-owner and actual-Quadlet fixtures reproduce that mapping.
Rollback fixture now forces an account-policy failure after noauth migration so
it still verifies restoration after a real DB mutation. These revised tests and
combined backend validation are in progress. A corrected embedded-helper build
and new live qualification remain required. Do not reuse the failed binary as
final release or mark the credential gate passed from earlier fixture results.
Release-note drift corrected to1.9.0/current upload behavior and File Browser/
Nostr additions. The checker now rejects stale descriptions/dates for an existing
version; its regression passes. Latest notes UI built and deployed dev/yaya index
SHA256 `97aab07e67eccc1bb3d215534b537b83e1372bf5c36b505b6127a24a2b629e23`.
Phone background/reconnect acceptance question is pending, not passed.
## Corrected credential qualification and mirror policy — 2026-10-05
The DAC_OVERRIDE correction passed all six real-image cases, including legacy
manifest ownership and restoration after an actual DB mutation. Actual disposable
Quadlet first start/restart passed with legacy ownership. Corrected helper SHA256
`e9e2fd94534130f10f19f81ebe0d4e382dca4338118393c7d1e30535a8478eb5`
also migrated the dev node's actual File Browser storage successfully: managed
login/folder200, private credential record, unchanged unrelated containers, and
manager/File Browser restored active. The old backend remains deployed pending
the corrected optimized build. Yaya credential/backend acceptance remains open.
Evidence: `/tmp/archy-190-filebrowser-ownership-integration.log`,
`/tmp/archy-190-filebrowser-ownership-quadlet.log`,
`/tmp/archy-190-filebrowser-ownership-live-dev.log`,
`/tmp/archy-190-filebrowser-ownership-dev-cloud.log`.
Updated isolated backend suite: 1,681 passed, zero failed, four ignored
(`/tmp/archy-190-filebrowser-ownership-backend.log`).
Browser protocol recovery also passes explicit CDP frozen-page/offline/reconnect
at both widths (`/tmp/archy-190-cloud-frozen-dev.log`); physical phone acceptance
is still pending and is not inferred from browser automation.
Operator selected ngit as the canonical contribution/review platform; Gitea
mirrors accepted main and release tag objects without requiring duplicate PRs.
Rule, contributor docs and read-only parity gate are committed as `138a541d`,
pushed to both mirrors and main/local parity verified. Disposable bare-repository
regression covers missing refs, partial pushes, divergence, annotation drift,
unpublished local commits, intentionally separate branches and inaccessible
remotes. Final release gate must additionally check the actual release tag.
## Alpha candidate: live Cloud and ACME qualification — 2026-10-05
Operator requires final version **1.9.0-alpha** and tag **v1.9.0-alpha**. Cargo,
frontend package/lock, changelog and What's New now agree; the unused unsuffixed
What's New block was removed. The optimized alpha build is in progress. Current
backend qualification SHA256 `e218e40f5c16c3d0cc4dc06c0a378c14b56b9087ded5c515b8a48351ceea3bcf`
is deployed on dev and yaya but predates this suffix change; it is not the final
artifact. Both returned backend health200 and managed Cloud login/folder200 with
unrelated container IDs/start times unchanged.
A real upload rerun initially failed after concurrent token refresh. A new unit
regression reproduced the race: mutable shared failure state let another login
turn a network interruption into a credential rejection. Authentication now
shares an in-flight request and returns its own retryability result. Regression
failed before and passes after. Full frontend: **1,211 passed / 148 files**.
Full alpha backend isolated suite: **1,681 passed, zero failed, four ignored**.
Deployed alpha UI index SHA256 on dev/yaya:
`67de835a25db59a483314eff583b809c3468c8529080bfa74c9962e44a6f54f9`.
Both real browser upload suites pass 390/1440px including partial writes, frozen
page/offline return, interrupted refresh, lost final replies, exact saved hash,
encoded filenames, origin-only bar, completion notification and cancellation.
Framework access was restored with the supplied updated SSH credential. Its
LND reports chain/graph sync; balance and channel queries work. Confirmed the
legacy File Browser still accepted admin/admin, then applied the exact qualified
helper with a private backup and bounded File Browser/manager stop-start. Both
managed and compatibility logins/folder reads200; admin/admin403; credential mode
0600; all other container IDs/start times unchanged. Prior backend retained until
final alpha deployment. Dashboard RPC session needs second-factor login; no
wallet funds were spent. Operator now reports Framework radio working; no reflash.
Local Pebble ACME **fresh and legacy nested layouts passed** actual pre-host
issuance, HTTP challenges, forced-HTTPS renewal, new certificate served, unknown
management404, trusted WSS, access controls, restart and forced-bind rollback.
Fixture fixes: modern NPM meta schema; explicit slirp loopback CA route; disable
random test-CA nonce rejection for deterministic route/renewal coverage. This is
an isolated test CA, not a public Let's Encrypt staging/ISO/reboot pass. All test
containers were cleaned up. Source NPM regression remains23/23.
Evidence: `/tmp/archy-190-alpha-backend-tests.log`,
`/tmp/archy-190-alpha-frontend-tests.log`,
`/tmp/archy-190-cloud-concurrent-login-before.log`,
`/tmp/archy-190-cloud-concurrent-login-after.log`,
`/tmp/archy-190-alpha-cloud-dev.log`, `/tmp/archy-190-alpha-cloud-yaya.log`,
`/tmp/archy-190-framework-secure-cloud.log`,
`/tmp/archy-190-framework-cloud-compatibility.log`,
`/tmp/archy-190-npm-acme-flat-6.log`, `/tmp/archy-190-npm-acme-nested.log`.
Public demo target clarified: https://demo.archipelago-foundation.org/, currently
reported1.8.8. Existing Docker Compose demo deployment located read-only; do not
confuse it with Yaya's v4v stack. Update after release, preserving rollback and
qualifying mock backend compatibility with new Cloud uploads. No demo deployed yet.
No OTA/catalog/ISO has been published.