Plant your ECN — stand up a PolitiCap syndicate downlink under the Nakhon Nayok hub. Same binary runs the regional market API, Redis caches, and an optional public HTML wire with server-imposed content filters.

What you get

The politicap-node package is a self-contained regional stack:

Component Role
bin/politicap-api Market API + optional edge HTML wire (one binary)
etc/politicap-api.yaml Node identity, uplink key, Redis, edge flags
db/schema.sql + db/seed.sql Schema + catalog seed
systemd/politicap-api.service Service unit
Redis Normal on every node — tickers + wire cache

Topology

Nakhon Nayok hub
        ▲
        │  X-ECN-Node-Key: pcn_…
        │  content: /api/ecn/v1/content/*
        │
   your regional node
   {city}.{country}.politicap.eu
        │
        ├─ /api/…     market API
        └─ /  /a/id   optional filtered HTML wire
              (Redis cache)
  • Humans sign up and trade on politicap.eu (apex). Your wire deep-links login / enroll / account there.
  • Your node is a downlink: market API + optional public wire.
  • Content policy is imposed on the hub. The edge may only narrow filters — never widen them.

Prerequisites

  • Linux + systemd (Debian/Ubuntu recommended)
  • MySQL or MariaDB 10.5+
  • Redis 6+ (localhost or private network) — treat as standard, not optional long-term
  • Outbound HTTPS to https://api.politicap.eu
  • Node API key from the hub (pcn_…) — private channel only
  • DNS for {city}.{country}.politicap.eu (+ TLS when live)

Need a downlink provisioned? support@politicap.eu

1. Unpack

tar -xzf politicap-node-*.tar.gz
cd politicap-node-*
sudo mkdir -p /opt/politicap-api/bin /etc/politicap-api
sudo cp bin/politicap-api /opt/politicap-api/bin/
sudo chmod 755 /opt/politicap-api/bin/politicap-api

2. Database

sudo mysql -e "CREATE DATABASE politicap CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'politicap'@'localhost' IDENTIFIED BY 'STRONG_PASSWORD';
GRANT ALL ON politicap.* TO 'politicap'@'localhost';
FLUSH PRIVILEGES;"

mysql -u politicap -p politicap < db/schema.sql
mysql -u politicap -p politicap < db/seed.sql

3. Redis

Every ECN node should run Redis for catalog and wire caches (logical DB 4 by default).

sudo apt install redis-server   # or point at your managed Redis
redis-cli ping                 # PONG

4. Configure

sudo cp etc/politicap-api.yaml.example /etc/politicap-api/politicap-api.yaml
sudo edit /etc/politicap-api/politicap-api.yaml

Minimum fields:

node:
  name: "Your node name"
  hostname: your-city.your-country.politicap.eu
  role: regional
  ecn_id: 1

listen:
  addr: "0.0.0.0:18082"

database:
  user: politicap
  password: "STRONG_PASSWORD"
  host: "127.0.0.1"
  port: "3306"
  name: politicap

uplink:
  url: "https://api.politicap.eu"
  api_key: "pcn_YOUR_KEY_FROM_HUB"

redis:
  addr: "127.0.0.1:6379"
  db: 4

public:
  site_url: https://politicap.eu
  api_url: https://your-city.your-country.politicap.eu

# Optional public HTML wire (filtered desk content)
edge:
  enabled: false
  title: "PolitiCap Your City"
  tagline: "Regional market wire"
  tenant: "your-city"
  lang: "en"
  signup_url: "https://politicap.eu/"
  login_url: "https://politicap.eu/?threedn_oidc=login"
  account_url: "https://politicap.eu/my-account/"
  agencies_deny: ["satire", "dox"]
  feed_ttl_seconds: 60
  article_ttl_seconds: 300

5. systemd

sudo cp systemd/politicap-api.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now politicap-api
curl -sS http://127.0.0.1:18082/healthz

6. Handshake

export KEY='pcn_…'
curl -sS -H "X-ECN-Node-Key: $KEY" \
  https://api.politicap.eu/api/ecn/v1/hello | jq .
curl -sS -H "X-ECN-Node-Key: $KEY" \
  https://api.politicap.eu/api/ecn/v1/content/policy | jq .

7. Catalog + sanitized wire API

curl -sS -H "X-ECN-Node-Key: $KEY" \
  'https://api.politicap.eu/api/ecn/v1/catalog/tickers?limit=50' | jq '.count'

curl -sS -H "X-ECN-Node-Key: $KEY" \
  'https://api.politicap.eu/api/ecn/v1/content/feed?lang=en' | jq '.count, .articles[0].title'

curl -sS -H "X-ECN-Node-Key: $KEY" \
  'https://api.politicap.eu/api/ecn/v1/content/posts/123' | jq '.title, .agency'

8. Edge HTML wire

Set edge.enabled: true, restart, reverse-proxy your hostname to :18082.

  • GET / — filtered article list (Redis-cached)
  • GET /a/{id} — article body
  • Header buttons: Sign up / Log in / Account → apex PolitiCap

Speech-sensitive regions (example cn.politicap.eu): hub policy can force agency allowlists and languages. The node binary never sees denied desks.

API reference (downlink → hub)

Method Path Auth
GET/POST /api/ecn/v1/hello node key
GET /api/ecn/v1/me node key
GET /api/ecn/v1/catalog/tickers node key
GET /api/ecn/v1/catalog/countries node key
GET /api/ecn/v1/catalog/cities node key
GET /api/ecn/v1/content/policy node key
GET /api/ecn/v1/content/feed node key
GET /api/ecn/v1/content/posts/{id} node key

Also accepted: Authorization: Bearer pcn_….

Security

  • Treat pcn_ keys as production secrets. Hub stores only a hash.
  • Do not commit keys or DB passwords.
  • Expose only TLS on the public hostname; keep Redis and MySQL private.
  • Edge content is intentionally filtered. Do not bypass the hub export with raw WordPress credentials on the node.

What this release still leaves for later

  • Automatic apply of catalog pull into the local DB
  • Cross-ECN order batching (ecn_to_ecn)
  • Regional DutchBud ledgers (ledger remains hub-central)

Package source

Hub operators build with scripts/build-node-package.sh in politicap-api. Operators receive a versioned tarball plus a one-time API key.

Related: Technical index · Android app · Dual IPO