feat: integrate local Blossom, reviewed nsites and scoped app access
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# Blossom on Archipelago
|
||||
|
||||
Candidate package, not a published catalogue release. Follow
|
||||
[`docs/app-developer-guide.md`](../../docs/app-developer-guide.md) and
|
||||
[`docs/candidate-catalog-qualification.md`](../../docs/candidate-catalog-qualification.md)
|
||||
for lifecycle and catalogue acceptance.
|
||||
|
||||
## Package contract
|
||||
|
||||
- MIT upstream `hzrd149/blossom-server` 6.4.1, source commit
|
||||
`a492dc61c4a581bbd0992546b2aec6f9aa543f75`. The Dockerfile verifies the source
|
||||
archive SHA-256 and uses upstream's frozen dependency lock for the server.
|
||||
- Manifest-owned local build; the runtime payload must include `docker/blossom`.
|
||||
No unpublished registry image is advertised. Initial installation needs access
|
||||
to the open-source build dependencies; normal startup uses cached dependencies.
|
||||
- Rootless container, read-only root, no capabilities, no new privileges,
|
||||
explicit `slirp4netns`. Host port 8191 binds IPv4 loopback behind AppGate.
|
||||
Keep that private backend binding: any FIPS/IPv6 ingress belongs at the gate.
|
||||
- Persistent data and SQLite under `/var/lib/archipelago/blossom/data`.
|
||||
Preserve this directory on uninstall. No automatic expiry/pruning, automatic
|
||||
mirroring, media conversion, or upstream administration dashboard.
|
||||
- Uploads require BUD-11 signatures from the profile identities supplied by
|
||||
`{{NODE_IDENTITY_PUBKEYS}}`. No profile means startup fails closed. Changes to
|
||||
that allowlist take effect on restart, including revocation of removed profiles.
|
||||
The appliance identity is excluded. Listing requires the owner's signature.
|
||||
- The custom local UI loads the canonical, host-managed `nostr-provider.js`
|
||||
through the documented lifecycle hook. A missing provider fails verification.
|
||||
The UI uses the platform identity chooser and ordinary NIP-07 signing; there
|
||||
is no generated browser key, nsec input, or second consent modal.
|
||||
- Upload authorization is scoped to the file hash, actual server hostname and
|
||||
five-minute expiry. Local upload does not send a public Nostr announcement.
|
||||
- Uploaded files are returned as sandboxed attachments. Untrusted HTML/SVG must
|
||||
not acquire this app's origin or signer access. Published website rendering
|
||||
needs the separate website origin, not a relaxation of this policy.
|
||||
|
||||
AppGate protects reads as well as the UI. Blossom itself is content-addressed,
|
||||
not an encrypted per-user vault: other authorized node users who know a hash can
|
||||
retrieve its bytes. Do not open the whole app gate to publish one website. Public
|
||||
asset serving must authorize exact selected hashes; external replication requires
|
||||
its own explicit content/destination review. An inaccessible local URL is not a
|
||||
working public Blossom endpoint.
|
||||
|
||||
## Qualification evidence — 2026-10-08
|
||||
|
||||
- Manifest preflight: 16 passed, no warnings. Generated catalogue drift: zero.
|
||||
- Candidate built and started on Framework with read-only root and the declared
|
||||
resource/security constraints. All protocol tests use synthetic identities and
|
||||
files; no public relay or external Blossom server is contacted.
|
||||
- `tests/apps/blossom/protocol.ts` passed against the candidate: authenticated
|
||||
upload/readback, exact hash/size/bytes, wrong identity/server/expired/anonymous
|
||||
upload rejection, owner-only listing, disabled mirror, canonical provider and
|
||||
health endpoint. HTML response has sandbox CSP and attachment headers.
|
||||
- Fixture survived container recreation with the same data directory and restart
|
||||
with explicit slirp4netns. An earlier test using Podman's default pasta hit a
|
||||
transient port teardown conflict; that is not the package's configured network.
|
||||
- Canonical Rust parser: all shipped manifests parse in the isolated test runner.
|
||||
- Setup/source tests: 13 passed, dashboard typecheck passed including the final
|
||||
receipt-review presentation changes.
|
||||
- Packaged UI passed a real Chromium test at mobile width: explicit identity
|
||||
chooser, consent before upload, signer refusal blocks upload, hash/host-scoped
|
||||
upload, consent reset and no external requests. Signer and upload transport
|
||||
were mocked for this UI test; live protocol checks above are separate.
|
||||
- Framework's normal installer succeeded after the operator temporarily disabled
|
||||
dashboard 2FA. Candidate manifest and build context are staged in the runtime
|
||||
payload. The app is healthy, with its canonical bridge installed by the hook,
|
||||
read-only root, slirp4netns and a loopback backend behind AppGate. Anonymous
|
||||
HTTPS access on port 8191 returns the gate's 401 sign-in page.
|
||||
- Real HTTPS tab signer acceptance passed: profile chooser, refusal prevents any
|
||||
upload, and an approved BUD-11 authorization stores a synthetic local file.
|
||||
No real identity key was exported or public Nostr event sent. Existing native
|
||||
Bitcoin/LND processes retained their original start times during installation.
|
||||
- No signed catalogue, source proposal, public Nostr event, OTA or ISO published.
|
||||
|
||||
- Real HTTP tab signing also passed. Normal app stop/start, restart with a new
|
||||
container, uninstall with `preserve_data:true`, reinstall, and management restart
|
||||
all preserved the uploaded synthetic file, verified by hash. Native Bitcoin/LND
|
||||
processes retained their original start times.
|
||||
- Local website archive integration is implemented in source: an explicit action
|
||||
signs a hash/server-scoped upload, stores the saved draft through the local
|
||||
manifest-owned Blossom backend, verifies exact readback and records a receipt.
|
||||
It does not announce or replicate anything. Its backend RPC is not yet deployed.
|
||||
|
||||
Still required before release: cross-profile identity switch (only one profile
|
||||
was available), HTTP/HTTPS iframe and physical companion validation, arranged
|
||||
reboot, integrated website archive acceptance, then reviewed source/mirror parity
|
||||
and signed catalogue gates. Selective public asset routes remain separate work;
|
||||
the authenticated app address must never be advertised as a public Blossom URL.
|
||||
Restore dashboard 2FA with the operator after live testing.
|
||||
Reference in New Issue
Block a user