diff --git a/AI_CONTEXT.md b/AI_CONTEXT.md index b82aa80..3ce8f1c 100644 --- a/AI_CONTEXT.md +++ b/AI_CONTEXT.md @@ -9,6 +9,7 @@ - [Configuration System](#configuration-system) - [Node vs Client Roles](#node-vs-client-roles) - [Network Protocol & Data Flow](#network-protocol--data-flow) +- [Gateway Service](#gateway-service) - [Build & Development](#build--development) - [API Reference](#api-reference) - [Troubleshooting](#troubleshooting) @@ -179,6 +180,69 @@ network/ --- +## Gateway Service + +The Gateway provides an HTTP(S)/WebSocket surface over the network client with strict namespace enforcement. + +- **Run:** + +```bash +make run-gateway +# Env overrides: GATEWAY_ADDR, GATEWAY_NAMESPACE, GATEWAY_BOOTSTRAP_PEERS, +# GATEWAY_REQUIRE_AUTH, GATEWAY_API_KEYS +``` + +- **Auth:** When `RequireAuth` is enabled, endpoints require either: + - JWT (issued by this gateway; JWKS: `GET /v1/auth/jwks` or `/.well-known/jwks.json`) + - API Key (via `Authorization: Bearer ` or `X-API-Key`), optionally mapped to a namespace + - Wallet verification uses Ethereum EIP-191 `personal_sign`: + - `POST /v1/auth/challenge` returns `{nonce}`. Clients must sign the exact nonce string. + - `POST /v1/auth/verify` expects `{wallet, nonce, signature}` with 65-byte r||s||v hex (0x allowed). `v` normalized (27/28 or 0/1). Address match is case-insensitive. Nonce is marked used only after successful verification. + +- **Namespace Enforcement:** Storage and PubSub are internally prefixed `ns::::...`. Ownership of namespace is enforced by middleware for routes under `/v1/storage*`, `/v1/apps*`, and `/v1/pubsub*`. + +### Endpoints + +- Health/Version + - `GET /health`, `GET /v1/health` + - `GET /v1/status` + - `GET /v1/version` → `{version, commit, build_time, started_at, uptime}` + +- JWKS + - `GET /v1/auth/jwks` + - `GET /.well-known/jwks.json` + +- Auth + - `POST /v1/auth/challenge` + - `POST /v1/auth/verify` + - `POST /v1/auth/register` + - `POST /v1/auth/refresh` + - `POST /v1/auth/logout` + - `GET /v1/auth/whoami` + +- Storage + - `POST /v1/storage/get`, `POST /v1/storage/put`, `POST /v1/storage/delete` + - `GET /v1/storage/list?prefix=...`, `GET /v1/storage/exists?key=...` + +- Network + - `GET /v1/network/status`, `GET /v1/network/peers` + - `POST /v1/network/connect`, `POST /v1/network/disconnect` + +### PubSub + +- WebSocket + - `GET /v1/pubsub/ws?topic=` + - Server sends messages as binary frames; 30s ping keepalive. + - Client text/binary frames are published to the same namespaced topic. + +- REST + - `POST /v1/pubsub/publish` → body `{topic, data_base64}` → `{status:"ok"}` + - `GET /v1/pubsub/topics` → `{topics:["", ...]}` (names trimmed to caller namespace) + +Security note: CORS and WS origin checks are permissive for development; harden for production. + +--- + ## Build & Development ### **Prerequisites** @@ -192,6 +256,7 @@ network/ make build # Build all executables make test # Run tests make run-node # Start node (auto-detects bootstrap vs regular) +make run-gateway # Start HTTP gateway (env overrides supported) ``` ### **Development Workflow** diff --git a/Makefile b/Makefile index 6a418ce..35d3d02 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,8 @@ build: deps @mkdir -p bin go build -ldflags "$(LDFLAGS)" -o bin/node ./cmd/node go build -ldflags "$(LDFLAGS)" -o bin/network-cli cmd/cli/main.go - go build -ldflags "$(LDFLAGS)" -o bin/gateway ./cmd/gateway + # Inject gateway build metadata via pkg path variables + go build -ldflags "$(LDFLAGS) -X 'git.debros.io/DeBros/network/pkg/gateway.BuildVersion=$(VERSION)' -X 'git.debros.io/DeBros/network/pkg/gateway.BuildCommit=$(COMMIT)' -X 'git.debros.io/DeBros/network/pkg/gateway.BuildTime=$(DATE)'" -o bin/gateway ./cmd/gateway @echo "Build complete! Run ./bin/network-cli version" # Clean build artifacts @@ -46,6 +47,22 @@ run-node3: @echo "Starting regular node3 with config..." go run ./cmd/node --config configs/node.yaml +# Run gateway HTTP server +# Usage examples: +# make run-gateway # uses defaults (:8080, namespace=default) +# GATEWAY_ADDR=":8081" make run-gateway # override listen addr via env +# GATEWAY_NAMESPACE=myapp make run-gateway # set namespace +# GATEWAY_BOOTSTRAP_PEERS="/ip4/127.0.0.1/tcp/4001/p2p/" make run-gateway +# GATEWAY_REQUIRE_AUTH=1 GATEWAY_API_KEYS="key1:ns1,key2:ns2" make run-gateway +run-gateway: + @echo "Starting gateway HTTP server..." + GATEWAY_ADDR=$(or $(ADDR),$(GATEWAY_ADDR)) \ + GATEWAY_NAMESPACE=$(or $(NAMESPACE),$(GATEWAY_NAMESPACE)) \ + GATEWAY_BOOTSTRAP_PEERS=$(GATEWAY_BOOTSTRAP_PEERS) \ + GATEWAY_REQUIRE_AUTH=$(GATEWAY_REQUIRE_AUTH) \ + GATEWAY_API_KEYS=$(GATEWAY_API_KEYS) \ + go run ./cmd/gateway + # Run basic usage example run-example: @echo "Running basic usage example..." @@ -171,6 +188,7 @@ help: @echo " run-node - Start bootstrap node" @echo " run-node2 - Start second node (requires JOINADDR, optional HTTP/RAFT/P2P)" @echo " run-node3 - Start third node (requires JOINADDR, optional HTTP/RAFT/P2P)" + @echo " run-gateway - Start HTTP gateway (flags via env: GATEWAY_ADDR, GATEWAY_NAMESPACE, GATEWAY_BOOTSTRAP_PEERS, GATEWAY_REQUIRE_AUTH, GATEWAY_API_KEYS)" @echo " run-example - Run usage example" @echo " run-cli - Run network CLI help" @echo " show-bootstrap - Show example bootstrap usage with flags" diff --git a/README.md b/README.md index 8e1a20a..08914e1 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ A robust, decentralized peer-to-peer network built in Go, providing distributed - [Deployment & Installation](#deployment--installation) - [Configuration](#configuration) - [CLI Usage](#cli-usage) +- [HTTP Gateway](#http-gateway) - [Development](#development) - [Troubleshooting](#troubleshooting) - [License](#license) diff --git a/go.mod b/go.mod index 9acfc9e..18f309c 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ toolchain go1.24.1 require ( github.com/ethereum/go-ethereum v1.13.14 + github.com/gorilla/websocket v1.5.3 github.com/libp2p/go-libp2p v0.41.1 github.com/libp2p/go-libp2p-pubsub v0.14.2 github.com/multiformats/go-multiaddr v0.15.0 @@ -34,7 +35,6 @@ require ( github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20250208200701-d0013a598941 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.3 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/holiman/uint256 v1.2.4 // indirect github.com/huin/goupnp v1.3.0 // indirect