Files
archy/docker/podsteadr/UPSTREAM.md
T

6.3 KiB

Podsteadr exact-source adapter

This adapter is based only on the frozen, read-only Podsteadr Git object:

  • commit: eb20e88f582e1ddb0f32e8acf90cd9e77ec63b8f
  • tree: be6cf1d033f17ab53f23e5b8e5c7f4492f18e2f8
  • authored/committed: 2026-07-31T11:08:20Z
  • subject: fix: switch HLS output from low-latency to standard mode

The source-stage receipt intentionally does not establish that this was the source tested by the earlier unpinned packaging proposal. That proposal is not an input to this adapter.

podsteadr-archipelago.patch removes first-valid-login administrator claiming. The app instead requires PODSTEADR_ADMIN_PUBKEYS, rendered by the manifest from Archipelago's public-only {{NODE_IDENTITY_PUBKEYS}} contract. Missing or malformed bindings stop startup. An empty admin slot can be claimed only by one of those keys. Existing administrators and user rows are preserved and never silently reassigned by this patch.

Cookie-authenticated state-changing requests additionally require an exact Origin match against PUBLIC_URL or optional, explicit PODSTEADR_TRUSTED_ORIGINS. Safe cookie reads and public reads remain available without an Origin check. NIP-98 authentication remains request-bound and builds acceptable URLs only from those configured origins; Host and X-Forwarded-* headers cannot expand the trust boundary.

Paid invoice confirmation atomically claims a quote by moving it from pending to paid before minting. Concurrent confirmation and restart retry therefore fail closed rather than invoking the mint twice. A paid quote that did not reach settled remains an explicit manual/protocol-reconciliation state; this adapter does not infer a refund, request another invoice, or retry an external financial operation with an unknown outcome.

The original security adapter tree is 4aaa497444f4d1018991b3d5a691d91f342cbab6; that patch SHA-256 remains 68025cccb6d69ff114115f99fab18416797b02aa947d1ba46fb52578086551e4. The additive podsteadr-lifecycle.patch handles SIGTERM/SIGINT by closing Fastify, the status poller, relay pool and SQLite, with a bounded failure exit. The prior packaged PID-1 process required SIGKILL after a five-second stop; the lifecycle fixture now requires exit 0, not merely preserved bytes afterward. Lifecycle patch SHA-256: 4b5b0fe46dcd8aa7eb9583d36bee3bd3cc135b3917ccd45703ffd7969bf8b9dd. The lifecycle-only tree was b7205e36559ec2110be648686586e6aa1221dd25. podsteadr-responsive.patch corrects the packaged navigation's493px width at a 390px viewport by allowing genuine wrapping, not hiding overflow. Actual packaged media/browser and390/1440px layout checks cover the change. It does not alter backend/auth/payment behavior. The responsive-only tree was 9fd59884e20c4c976c3b8b54ffb4270ece7c62da.

podsteadr-native-bridge.patch adds the missing canonical provider script with explicit data-app-id="podsteadr" and data-no-nip98: Podsteadr owns its login request and must not invoke the provider's unrelated automatic-login endpoint. The bridge-only upstream tree before receipt files was 05084117f72a61c8dd3dbd96ccc81b60f73e1e79.

podsteadr-server-key.patch adds a Linux-container key-only bootstrap and hardens the server's existing identity loader. Both use the same function and preserve existing key bytes/inode. New files are fsynced before no-clobber publication; config/root directory descriptors are pinned, symlinks and unsafe permissions are refused, and reads are bounded. Existing malformed, hardlinked, or nonprivate keys fail closed without reset, chmod, rotation or secret output. Missing keys beside existing database/other application data also refuse; normal startup establishes identity before opening/migrating SQLite so identity loss cannot silently generate a new signer. A reader racing the temporary second hardlink may refuse and require an explicit retry; it never replaces the winner. Crash remnants are preserved for inspection, not silently treated as permission to regenerate an identity.

Run node dist/provision-server-key.js /data only in a reviewed provisioning context with an existing owned data directory. It emits {version:1,publicKey} and loads no HTTP, database, relay or financial services. It does not configure Blossom, authorize arbitrary uploaders, rotate keys, or install anything. The fixture's opt-in PODSTEADR_KEY_BOOTSTRAP=1 checks that bootstrap identity matches normal startup and recreation, and allows sidecars to start before the app. The same actual package also passes a synthetic nonempty-data key-loss negative: startup refuses without changing SQLite or regenerating the key; restoring the retained exact inode/bytes restores the original authenticated app. This is a fixture repair, not an automatic product recovery policy. Final logout assertions remain after restoration (not before reuse of the saved session). Production manager hooks, durable public-key allowlist binding, nonempty migration and independent security review remain gates, not permissions granted by this CLI.

Current expected upstream tree: 29e47624ba86572d278411d229e24f4822046021. Server-key patch SHA-256: 090b7564cec6a05ab3828f6f4c5fb1451d986cd766133ea1e35b9c60e2ee02cd. The source test gate builds first because bootstrap CLI regressions execute the compiled command. Fifteen new key cases and all106 server tests pass in isolation; these are not independent review or managed installation acceptance.

The local build copies neode-ui/public/nostr-provider.js from the exact platform candidate into the image and records .archipelago-provider-sha256 separately from the upstream tree. The package test checks served JavaScript against that receipt and checks the script attributes. This corrects a missing package input, not native-broker, operator identity or installed trust acceptance. Dashboard media tests use an explicitly synthetic signer; they do not certify the broker.

Use prepare-source.sh with an explicit source Git directory and a new output directory. It exports the recorded commit without modifying the source checkout, verifies its tree, checks and applies the patch, and records the resulting tree. Source acquisition remains outside this adapter until a sanitized canonical public source location is approved; a local version label is not provenance.

This is source-stage material, not a reviewed image, signed catalog entry, or installed-node qualification.