Magazi is a content distribution platform that gates access to files using ATProtocol (Bluesky) identity and cryptographic proofs.
download.ngerakines.me/
···11+MIT License
22+33+Copyright (c) 2026 Nick Gerakines
44+55+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
66+77+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
88+99+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+118
README.md
···11+# Magazi
22+33+Magazi is a content distribution platform that gates access to files using ATProtocol (Bluesky) identity and cryptographic proofs. Users authenticate via ATProtocol OAuth, and file access is controlled through flexible JSONLogic rules that can require authentication, supporter status, or specific proof records.
44+55+## Attestations
66+77+This project uses [atproto-attestation](https://tangled.org/smokesignal.events/atproto-identity-rs/tree/main/crates/atproto-attestation) to verify cryptographic proofs and builds on top of the attestation implementation from [ATProtoFans](https://atprotofans.com/).
88+99+Attestations in ATProtocol are CID-first: records are prepared with signature metadata, serialized to DAG-CBOR, and the resulting content identifier is signed with elliptic curve cryptography. The signature includes a repository binding that prevents replay attacks across repositories.
1010+1111+When a user authenticates, Magazi fetches their `com.atprotofans.supporter` records and verifies the embedded attestations. Each supporter record contains StrongRef pointers to proof records signed by the creator and broker. These proofs are transparent and auditable—anyone can verify that support relationships are genuine.
1212+1313+## Getting Started
1414+1515+### Prerequisites
1616+1717+- Rust 1.75+
1818+- An ATProtocol identity (DID) for the creator
1919+- OAuth client credentials registered with your PDS
2020+2121+### Running
2222+2323+1. Clone the repository
2424+2. Create a `catalog.json` file defining your content (see Configuration)
2525+3. Set required environment variables
2626+4. Run the server:
2727+2828+```bash
2929+cargo run
3030+```
3131+3232+## Configuration
3333+3434+Configuration is environment-variable driven:
3535+3636+| Variable | Description |
3737+|----------|-------------|
3838+| `HTTP_PORT` | Server port (required) |
3939+| `HTTP_EXTERNAL` | External domain for OAuth callbacks (e.g., `magazi.example.com`) |
4040+| `HTTP_COOKIE_KEY` | Base64-encoded 64+ byte key for session cookies |
4141+| `OAUTH_CLIENT_CREDENTIALS` | Private signing key for OAuth client |
4242+| `CREATOR_IDENTITY` | Creator's DID (e.g., `did:plc:abc123`) |
4343+| `BROKER_IDENTITY` | Broker's DID for proof verification |
4444+| `DOWNLOAD_KEY` | Private key for JWT download tokens |
4545+| `FILES` | Filesystem path to stored files |
4646+| `CATALOG` | Path to `catalog.json` file |
4747+4848+### Catalog Format
4949+5050+The catalog is a JSON array of entries:
5151+5252+```json
5353+[
5454+ {
5555+ "id": "bafkreif2gmzhha...",
5656+ "name": "My File",
5757+ "description": "Description of the file",
5858+ "content_type": "application/pdf",
5959+ "requirements": {}
6060+ }
6161+]
6262+```
6363+6464+## Access Rules
6565+6666+Each catalog entry has a `requirements` field containing a JSONLogic rule evaluated against the user's entitlement context. The context includes:
6767+6868+- `authenticated` - Boolean, true if user is logged in
6969+- `did` - User's decentralized identifier
7070+- `handle` - User's handle
7171+- `supporter` - Supporter record data
7272+- `supporterProof` - Cryptographic proof from creator
7373+- `brokerProof` - Cryptographic proof from broker
7474+7575+### Examples
7676+7777+**Anyone can access** (no requirements):
7878+```json
7979+{
8080+ "requirements": {}
8181+}
8282+```
8383+8484+**Only logged in users can access**:
8585+```json
8686+{
8787+ "requirements": {
8888+ "!!": [{ "var": "authenticated" }]
8989+ }
9090+}
9191+```
9292+9393+**Only supporters can access** (requires both proofs):
9494+```json
9595+{
9696+ "requirements": {
9797+ "and": [
9898+ { "!!": [{ "var": "supporterProof" }] },
9999+ { "!!": [{ "var": "brokerProof" }] }
100100+ ]
101101+ }
102102+}
103103+```
104104+105105+**Only a specific identity can access**:
106106+```json
107107+{
108108+ "requirements": {
109109+ "==": [{ "var": "did" }, "did:plc:specificuser123"]
110110+ }
111111+}
112112+```
113113+114114+## License
115115+116116+MIT License
117117+118118+Copyright 2026 Nick Gerakines