Import the MetaMesh app family from Worph/AppStore
23 apps (MetaCore, the library/network/client tiers and 13 MetaFeeder*) move out of the general-purpose Worph/AppStore into their own store so the MetaMesh family releases on its own cadence. - asset URLs repointed to cdn.jsdelivr.net/gh/Worph/MetaAppStore@main - store scaffolding added (category/recommend/featured lists, licence, contributing, gitattributes) - psd-source/meta-icons-v2 icon generator follows the apps MetaMCP stays in Worph/AppStore: it is third-party metatool-ai software, not part of MetaMesh.
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# MetaShare — Rationale
|
||||
|
||||
## What deviation / exception is being requested
|
||||
|
||||
1. `metashare-app` runs `user: 0:0`.
|
||||
2. It publishes host port `4001/tcp` (libp2p).
|
||||
3. It mounts `/DATA/AppData/metacore/meta-core` — another app's AppData directory.
|
||||
4. Six HTTP paths bypass the SSO gate and are proxied straight to the backend:
|
||||
`/health`, `/api/peers*`, `/api/peer/*`, `/api/file/*`, `/api/search*` and
|
||||
`/api/services`.
|
||||
|
||||
## Why it is necessary
|
||||
|
||||
1. MetaShare writes its service registration into `/meta-core/services/`, a directory
|
||||
created and owned by MetaCore's root-running container.
|
||||
2. libp2p is **not HTTP**. Caddy is an HTTP reverse proxy and cannot carry it, and remote
|
||||
peers resolve this node's public multiaddr from the kad-DHT and dial it directly. Without
|
||||
a published, inbound-reachable TCP port the node can only make outbound connections and
|
||||
never serves bytes to the swarm. The app therefore carries the reserved
|
||||
`needs-public-ip` tag so a user behind CGNAT or the mesh-router tunnel can see the
|
||||
limitation before installing.
|
||||
3. `/meta-core` is the shared leader-election and service-discovery directory. MetaCore is
|
||||
a hard prerequisite of this app.
|
||||
4. Those are the **federation surface**: remote MetaShare peers call them to enumerate
|
||||
peers, resolve records, search, and fetch blocks. A remote peer is a machine client with
|
||||
no cookie jar and no way to complete an interactive OIDC redirect, so gating them makes
|
||||
the app unable to federate at all — which is its only function. Every other path,
|
||||
including the whole dashboard, stays behind the gate.
|
||||
|
||||
## Security mitigations in place
|
||||
|
||||
- Public ingress terminates at the AppShield sidecar (`ghcr.io/yundera/appshield:2.0.9`),
|
||||
which gates every path behind the PCS's Authelia SSO over OIDC. The backend carries no
|
||||
Caddy labels and publishes no HTTP port to the host, so it is reachable only from the
|
||||
`pcs` Docker network.
|
||||
- Every service declares `cpu_shares`, and the memory-heavy ones a hard `mem_limit` with
|
||||
`memswap_limit` equal to it (swap disabled, so the container is OOM-killed rather than
|
||||
pushing the host into swap).
|
||||
- Image tags are pinned; no `:latest` anywhere in the stack.
|
||||
|
||||
- The bypassed paths are read-only federation endpoints scoped to content the user has
|
||||
explicitly shared. They expose no configuration, no dashboard and no write operation, and
|
||||
they serve exactly what this node already publishes to the public swarm over libp2p — so
|
||||
gating them would protect nothing that the DHT does not already carry.
|
||||
- The published port speaks libp2p only. libp2p transport is authenticated and encrypted
|
||||
(Noise) and peer identity is a public key, so an unauthenticated dial cannot read
|
||||
anything the node has not chosen to publish to the swarm. The HTTP API stays on
|
||||
`expose:` behind AppShield.
|
||||
|
||||
## Alternatives considered and rejected
|
||||
|
||||
- **Proxy libp2p through Caddy.** Not possible: Caddy fronts HTTP, and the DHT advertises a
|
||||
raw TCP multiaddr.
|
||||
- **Outbound-only / relayed transport.** Works for reachability but not for serving: a node
|
||||
nobody can dial contributes no bytes, which is the app's entire function.
|
||||
- **Run as `$PUID:$PGID`.** Fails writing into MetaCore's root-owned
|
||||
`/meta-core/services/`.
|
||||
|
||||
## Data protection
|
||||
|
||||
MetaShare's own store lives under `/DATA/AppData/metashare/{config,data}/`, declared in
|
||||
`x-compose-app.folders` and archived by Maison on uninstall. Only content the user has
|
||||
explicitly shared is published to the swarm; nothing under `/DATA/Documents`,
|
||||
`/DATA/Downloads` or `/DATA/Media` is mounted into this container at all.
|
||||
Reference in New Issue
Block a user