diff --git a/README.ar.md b/README.ar.md new file mode 100644 index 0000000..2470c9d --- /dev/null +++ b/README.ar.md @@ -0,0 +1,199 @@ +> **ترجمة مجتمعية (مسودة)** — سياسة NTARI رقم P2-002، البث العالمي المتعدد اللغات. المصدر: README.md (الأصل الإنجليزي، لقطة بتاريخ 2026-07-29). مسودة مجتمعية بمساعدة الترجمة الآلية، في انتظار مراجعة المشرف الإقليمي وفقًا للبند §3.1 من P2-002. تبقى المواصفات التقنية الأساسية بالإنجليزية وفقًا للبند §2.2. +> +> تصحيحات الترجمة مساهمات نرحّب بها ونقدّرها كسائر المساهمات، فإذا لاحظت خطأً +> في هذه الترجمة فيمكنك إصلاحه بنفسك عبر إنشاء fork للمستودع وفتح pull +> request: https://github.com/NTARI-RAND/SoHoLINK + +# SoHoLINK + +[![إصدار Go](https://img.shields.io/badge/Go-1.24%2B-blue.svg)](https://golang.org) +[![الترخيص](https://img.shields.io/badge/License-AGPL%203.0-blue.svg)](LICENSE.txt) +[![CI](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml/badge.svg)](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml) + +**المنسّق المرجعي لركيزة الحوسبة SoHoLINK / Cloudy.** يحوّل SoHoLINK القدرة الخاملة +في الحوسبة والتخزين والطباعة لدى الأجهزة التي يملكها المشاركون إلى سوق منسَّقة: +يساهم الأعضاء بعتادهم عبر واجهة أمامية ويكسبون مدفوعات حقيقية بالعملة النظامية (fiat)؛ +ويشتري أعضاء آخرون قدرات الحوسبة والتخزين والطباعة وشبكة توصيل المحتوى (CDN) عند الطلب. + +> **الدور في سطر واحد:** SoHoLINK هو **المنسّق** — يُنظّم توزيع العمل +> على العُقد ويُسوّي حساباته. وهو **ليس** اقتصاد الأعضاء، وهو جزء +> **قابل للاستبدال**. راجع [`CONFORMANCE.md`](CONFORMANCE.md) للاطلاع على إعلان الدور +> الكامل بمصطلحات المعمارية نفسها. + +--- + +## ما هو SoHoLINK + +يؤدّي SoHoLINK **التنسيق التشغيلي على جانب العُقدة** لركيزة قائمة على معمارية +JFA (Janus-Facing Architecture): + +- **التعرّف على العُقد** — تُعلن العُقد عن العمل الذي ستؤديه عبر قوائم قدرات موقَّعة. +- **المطابقة والجدولة** — توزيع أحمال العمل على العُقد (مع مراعاة الموقع، ومراعاة الخمول، واحترام الانسحاب). +- **دورة حياة التوظيف** — العرض → القبول/الرفض → التنفيذ → الإبلاغ → التسوية، مع نافذة زمنية للنزاعات. +- **إعلانات الرسوم** — لا توجد الرسوم إلا كرسائل موقَّعة من المنسّق، مفهومة وقابلة للطعن. +- **التسوية بالعملة النظامية** — صرف المدفوعات للمساهمين عبر Stripe Connect. +- **اتحاد الواجهات الأمامية** — هدف تصميمي (راجع *الحالة* أدناه)، ولم يُبنَ بعد. + +المنسّق هو **دور قابل للتوصيل والاستبدال.** يمكن لأي تنفيذ مطابق أن يحلّ محلّه، +ويمكن لأي واجهة أمامية أن تُشغّل منسّقها الخاص أو أن تُطابق مباشرةً مع العُقد. +لا شيء في الشبكة مُلزَم بالمرور عبر هذا المنسّق بعينه — وانعدام هذا الامتياز +هو ما يمنع أي منسّق من أن يصبح محورًا لا يمكن إزالته. + +## ما *ليس* SoHoLINK + +- **ليس اقتصاد الأعضاء في JFA.** لا رصيد يُصدره الأعضاء، ولا ميثاق سمعة، + ولا سجل مختوم بالحوار، ولا فصل في النزاعات موجَّه للأعضاء. كل ذلك يقيم في **الواجهة + الأمامية** (Cloudy)، بحكم القاعدة المعمارية. +- **لا رموز (tokens) ولا محافظ (wallets).** التسوية بالعملة النظامية الخالصة عبر Stripe Connect، + وتبقى مفصولة فصلًا صارمًا عن رصيد الأعضاء في أي واجهة أمامية. +- **لا أشخاص على مسار البيانات (on the wire).** الأطراف المقابلة لـ SoHoLINK هي الواجهات الأمامية والعُقد؛ + والهوية الوحيدة التي يتعامل معها هي هوية حِمل العمل (`NodeID` مع ارتباط SPIFFE). + أما هوية الأعضاء ورصيدهم وسمعتهم ومعلوماتهم الشخصية (PII) فهي شؤون تخصّ الواجهة الأمامية. + +> **أسطح انتقالية.** إن وكيل العُقدة (`internal/agent`, `cmd/agent`)، وبوابة +> الأعضاء (`internal/portal`, `cmd/portal`, `web/`)، وجدول `participants` هي +> قدرات تملكها الواجهة الأمامية لكنها مُستضافة حاليًا في هذا المستودع من حقبة الدور المزدوج +> السابقة لـ SoHoLINK. تُصان عاملةً وتُوسَم بأنها انتقالية، في انتظار ترحيلها إلى +> الواجهة الأمامية. لا تعتبرها دور المنسّق على المدى الطويل. + +--- + +## موضعه في الحزمة + +``` +Front end (Cloudy) ──┐ + ├──► sohocloud-protocol (the dependency leaf: coordination only) +Coordinator (this) ──┘ +``` + +- يَستهلك SoHoLINK **[`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol)** + عند وسم إصدار منشور — وهي وحدة التنسيق ذات "الخصر النحيل" التي يتشاركها مع الواجهة الأمامية. +- ويُقدّم **مسار `/v0` الخاص بالبروتوكول** إلى جانب مسارات HTTP الحالية الخاصة به، فتتحدّث + الواجهة الأمامية المطابقة إليه عبر البروتوكول القياسي بينما تبقى المسارات الانتقالية + عاملة. +- ولا يعتمد على **أي** واجهة أمامية ولا على **أي** شيفرة تخصّ اقتصاد الأعضاء. فاقتصاد الأعضاء يقيم + فوق هذه الطبقة، ولا يجوز أبدًا أن يهاجر نزولًا إليها. + +--- + +## ثوابت JFA التي يحملها هذا المستودع + +| الثابت | كيف يُستوفى هنا | +|---|---| +| لا يظهر الأشخاص أبدًا على مسار البيانات | الأطراف المقابلة هي الواجهات الأمامية والعُقد؛ والهوية على مسار البيانات هي `NodeID` من نوع SPIFFE | +| هوية مشارك واحدة | جدول `participants` واحد — لا فصل بين المزوّد والمستهلك في المخطط ولا في الشيفرة | +| وضوح الرسوم | لا توجد الرسوم إلا كرسائل `FeeDeclaration` موقَّعة من المنسّق | +| العملة النظامية تبقى نظامية؛ والرصيد يبقى في موضعه | التسوية بـ Stripe Connect الخالص؛ مفصولة فصلًا صارمًا عن رصيد الأعضاء | +| لا عدم تكافؤ في المعلومات | التسعير والقياس والأرباح مرئية للمشاركين | +| فصل سطح الحَوْكمة | تعمل الإدارة والحَوْكمة على واجهة منفصلة محلية فقط — لا على الموقع العام، ولا خلف أعلام أدوار | +| المنشأ الداخل = الخارج | AGPL-3.0؛ توقيع DCO؛ بلا CLA | + +--- + +## الحزمة التقنية + +| الطبقة | التقنية | +|---|---| +| اللغة | Go 1.24+ | +| الويب | HTML مُصيَّر على الخادم عبر `html/template` في Go — بلا إطار JS وبلا خطوة بناء (يجب أن يعمل على هاتف Android من طراز 2019 على شبكة 3G وفي متصفحات التلفزيونات الذكية) | +| قاعدة البيانات | PostgreSQL 16 + TimescaleDB، و`pgx/v5` (بلا ORM) | +| تخزين الكائنات | MinIO (متوافق مع S3) | +| الهوية | SPIFFE/SPIRE — mTLS، وشهادات SVID من نوع X.509 قصيرة العمر | +| المدفوعات | Stripe Connect (بالعملة النظامية فقط) | +| النشر | Docker Compose خلف نفق Cloudflare | +| CI | GitHub Actions | + +--- + +## هيكل المستودع + +``` +cmd/ + orchestrator/ Coordinator service: matching, employment lifecycle, /v0 wire, settlement hooks + portal/ Member portal (transitional, front-end-owned) + agent/ Node agent (transitional, front-end-owned) + seed/ Dev/load-test seeder — never point at production +internal/ + api/ Control-plane HTTP API (+ protocol /v0 handlers via protocoladapter) + orchestrator/ Node registry, matching, placement scoring, job token issuance + scheduler/ Scoring-based placement (class, freshness, capacity, locality, idle) + protocoladapter/ Implements coordinator.Coordinator; mounts the /v0 wire + payment/ Stripe Connect: onboarding, charge, payout, webhook + identity/ SPIFFE integration, mTLS config, SPIFFE-binding middleware + store/ PostgreSQL pool + migrations + agent/ portal/ Transitional front-end-owned capabilities (see note above) +web/ Server-rendered templates + CSS +deploy/ Compose stack, SPIRE config, backup + deploy scripts +docs/ Architecture, operations, and session records +``` + +--- + +## البناء + +المتطلبات المسبقة: Go 1.24+، ونسخة عاملة من PostgreSQL 16 + TimescaleDB، وDocker (لتشغيل +الحزمة الكاملة). + +```bash +git clone https://github.com/NTARI-RAND/SoHoLINK +cd SoHoLINK + +# Build the coordinator and portal binaries +go build ./cmd/orchestrator +go build ./cmd/portal + +# Run tests (unit) +go test ./... + +# Run integration tests against an isolated test database +# (DB name MUST contain "test" — fixtures refuse to touch any other database) +TEST_DATABASE_URL="postgres://postgres:changeme@localhost:5432/soholink_test?sslmode=disable" \ + go test -tags integration ./... +``` + +تُطبَّق ترحيلات قاعدة البيانات عند بدء تشغيل الخدمة (golang-migrate، وهي عملية خاملة التكرار). +أما حزمة الإنتاج الكاملة — Postgres وSPIRE والمنسّق والبوابة وبوابة الدخول (ingress) — فتعمل عبر +Docker Compose تحت `deploy/`. + +--- + +## الحالة (بصراحة) + +- **مبنيّ وقيد التشغيل:** التعرّف على العُقد، والمطابقة والجدولة، ودورة حياة التوظيف، + والتسوية بالعملة النظامية (Stripe Connect)، وإعلانات الرسوم الموقَّعة من المنسّق، ومسار التنسيق + `/v0`، والمصادقة بالمُشغّل أو بـ SPIFFE، وهوية أحمال العمل عبر SPIFFE — كلها تعمل + في الإنتاج على **[soholink.org](https://soholink.org)** (نطاق الثقة + `spiffe://soholink.org`). +- **نشرٌ بمنسّق واحد.** أما الاتحاد بين المنسّقين ونقاط التحقّق المشهودة فهي + **هدف تصميمي لم يُبنَ** — والمشكلة المفتوحة رقم 7 في المعمارية + (الحوسبة السيادية تشتري خروجًا *ميكانيكيًا* لا *اقتصاديًا*) تنطبق بالكامل، وهي مُسمّاة + لا محلولة. +- **تسجيل المُشغّل** (الواجهة الأمامية بصفة مُشغّل) مُتحقَّق منه في الاختبارات لكنه لم + يكتمل من طرف إلى طرف في الإنتاج، في انتظار ناقل البريد للمصادقة الثنائية. +- **لا توجد عُقد تجريبية حيّة بعد.** يستهدف البرنامج التجريبي الأول مجتمعًا سكنيًا كثيف + السكان مجاورًا لمقر NTARI. +- **اقتصاد الأعضاء موجود في مكان آخر بشكل متعمَّد** — فالرصيد والميثاق والسجل تقيم في + الواجهة الأمامية (Cloudy)، طبقةً واحدة أعلى. + +--- + +## التوثيق + +| المستند | الوصف | +|---|---| +| [`CONFORMANCE.md`](CONFORMANCE.md) | إعلان الدور بمصطلحات JFA؛ وربط الثوابت بالآليات؛ والبدائل المؤقتة المُسمّاة | +| [`CLAUDE.md`](CLAUDE.md) | السياق الهندسي والاصطلاحات وسجل العمل | +| `docs/` | المعمارية، وأدلة التشغيل، وسجلات كل جلسة | + +بروتوكول التنسيق المشترك موصَّف في مستودع +[`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol) +(في `SPEC.md`). + +--- + +## الترخيص + +AGPL-3.0-or-later — راجع [`LICENSE.txt`](LICENSE.txt). يحفظ ترخيص AGPL الركيزة بأكملها +كمشاع دائم: اقرأها، وأعِد تنفيذها، وانسخها (fork)، وارحل. + +*Network Theory Applied Research Institute, Inc. — 501(c)(3) — EIN 92-3047136 — info@ntari.org* diff --git a/README.es.md b/README.es.md new file mode 100644 index 0000000..4245b97 --- /dev/null +++ b/README.es.md @@ -0,0 +1,208 @@ +> Traducción comunitaria (borrador) — Política P2-002 de NTARI, Difusión Global Multilingüe. Fuente: README.md (original en inglés, captura del 2026-07-29). Borrador comunitario asistido por máquina, pendiente de revisión por el mantenedor regional conforme a P2-002 §3.1. Las especificaciones técnicas centrales permanecen en inglés conforme a §2.2. +> +> ¿Encontraste un error en esta traducción? Tu corrección es una contribución +> bienvenida y valorada: haz un fork del repositorio y abre un pull request en +> https://github.com/NTARI-RAND/SoHoLINK. + +# SoHoLINK + +[![Versión de Go](https://img.shields.io/badge/Go-1.24%2B-blue.svg)](https://golang.org) +[![Licencia](https://img.shields.io/badge/License-AGPL%203.0-blue.svg)](LICENSE.txt) +[![CI](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml/badge.svg)](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml) + +**El coordinador de referencia del sustrato de cómputo SoHoLINK / Cloudy.** SoHoLINK +convierte la capacidad ociosa de cómputo, almacenamiento e impresión de las máquinas +propiedad de los participantes en un mercado coordinado: los miembros aportan hardware +a través de un front end y reciben pagos reales (en moneda fiduciaria); otros miembros +compran capacidad de cómputo, almacenamiento, impresión y CDN bajo demanda. + +> **Su rol, en una línea:** SoHoLINK es el **coordinador**: orquesta el trabajo +> entre nodos y lo liquida. **No** es la economía de miembros, y es una pieza +> **reemplazable**. Consulte [`CONFORMANCE.md`](CONFORMANCE.md) para la declaración +> completa del rol en los términos propios de la arquitectura. + +--- + +## Qué es SoHoLINK + +SoHoLINK realiza la **orquestación del lado de los nodos** para un sustrato de +Janus-Facing Architecture (JFA): + +- **Reconocimiento de nodos** — los nodos anuncian qué trabajo realizarán mediante listados de capacidades firmados. +- **Emparejamiento y planificación** — colocación de cargas de trabajo en los nodos (consciente de la localidad, consciente del estado ocioso y respetuosa de las exclusiones voluntarias). +- **Ciclo de vida del empleo** — oferta → aceptar/rechazar → ejecutar → reportar → liquidar, con una ventana de disputa. +- **Declaraciones de tarifas** — las tarifas existen únicamente como mensajes firmados por el coordinador, legibles y contestables. +- **Liquidación en moneda fiduciaria** — pagos a los contribuyentes mediante Stripe Connect. +- **Federación de front ends** — un objetivo de diseño (véase *Estado* más abajo), aún no construido. + +El coordinador es un **rol conectable y reemplazable.** Cualquier implementación conforme +puede sustituirlo, y un front end puede ejecutar su propio coordinador o emparejarse +directamente con los nodos. Nada en la red está obligado a enrutar a través de este +coordinador en particular; esa ausencia de privilegio es lo que impide que un coordinador +se convierta en un hub imposible de remover. + +## Qué *no* es SoHoLINK + +- **No es la economía de miembros de la JFA.** Sin crédito emitido por miembros, sin pacto + de reputación, sin registro sellado por diálogo, sin adjudicación de disputas de cara a + los miembros. Todo eso vive en el **front end** (Cloudy), por regla arquitectónica. +- **Sin tokens, sin billeteras.** La liquidación es puramente en moneda fiduciaria mediante + Stripe Connect, mantenida estrictamente separada del crédito de miembros de cualquier + front end. +- **Sin personas en el cable.** Las contrapartes de SoHoLINK son front ends y nodos; la + única identidad que maneja es la identidad de carga de trabajo (un `NodeID` con + vinculación SPIFFE). La identidad de los miembros, el crédito, la reputación y la + información personal identificable (PII) son asunto del front end. + +> **Superficies transicionales.** El agente de nodo (`internal/agent`, `cmd/agent`), el +> portal de miembros (`internal/portal`, `cmd/portal`, `web/`) y la tabla `participants` +> son capacidades propiedad del front end alojadas actualmente en este repositorio, +> herencia de la era anterior de doble rol de SoHoLINK. Se mantienen funcionando y +> etiquetadas como transicionales, a la espera de su migración al front end. No las trate +> como el rol de largo plazo del coordinador. + +--- + +## Dónde se ubica en el stack + +``` +Front end (Cloudy) ──┐ + ├──► sohocloud-protocol (the dependency leaf: coordination only) +Coordinator (this) ──┘ +``` + +- SoHoLINK **consume [`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol)** + en una etiqueta de versión publicada: el módulo de coordinación de "cintura delgada" + (thin waist) que comparte con el front end. +- **Sirve el cable `/v0` del protocolo** junto a sus propias rutas HTTP existentes, de + modo que un front end conforme se comunica con él mediante el protocolo estándar + mientras las rutas transicionales siguen funcionando. +- No depende de **ningún** front end ni de **ningún** código de la economía de miembros. + La economía de miembros vive por encima de esta capa y nunca debe migrar hacia abajo, + dentro de ella. + +--- + +## Invariantes de la JFA que este repositorio sostiene + +| Invariante | Cómo se cumple aquí | +|---|---| +| Las personas nunca aparecen en el cable | Las contrapartes son front ends y nodos; la identidad en el cable es un `NodeID` de SPIFFE | +| Identidad única de participante | Una sola tabla `participants` — sin división proveedor/consumidor en el esquema ni en el código | +| Legibilidad de las tarifas | Las tarifas existen únicamente como mensajes `FeeDeclaration` firmados por el coordinador | +| La moneda fiduciaria se queda fiduciaria; el crédito se queda en casa | La liquidación es puramente Stripe Connect; estrictamente separada del crédito de miembros | +| Sin asimetría de información | Los precios, la medición y las ganancias son visibles para los participantes | +| Superficie de gobernanza separada | La administración/gobernanza se ejecuta en una interfaz separada, de acceso exclusivamente local — nunca en el sitio público, nunca detrás de banderas de rol | +| Procedencia entrante = saliente | AGPL-3.0; firma DCO (sign-off); sin CLA | + +--- + +## Stack tecnológico + +| Capa | Tecnología | +|---|---| +| Lenguaje | Go 1.24+ | +| Web | HTML renderizado en el servidor mediante `html/template` de Go — sin framework de JS, sin paso de build (debe funcionar en un teléfono Android de 2019 con 3G y en navegadores de Smart TV) | +| Base de datos | PostgreSQL 16 + TimescaleDB, `pgx/v5` (sin ORM) | +| Almacenamiento de objetos | MinIO (compatible con S3) | +| Identidad | SPIFFE/SPIRE — mTLS, SVID X.509 de corta duración | +| Pagos | Stripe Connect (solo moneda fiduciaria) | +| Despliegue | Docker Compose detrás de un túnel de Cloudflare | +| CI | GitHub Actions | + +--- + +## Estructura del repositorio + +``` +cmd/ + orchestrator/ Coordinator service: matching, employment lifecycle, /v0 wire, settlement hooks + portal/ Member portal (transitional, front-end-owned) + agent/ Node agent (transitional, front-end-owned) + seed/ Dev/load-test seeder — never point at production +internal/ + api/ Control-plane HTTP API (+ protocol /v0 handlers via protocoladapter) + orchestrator/ Node registry, matching, placement scoring, job token issuance + scheduler/ Scoring-based placement (class, freshness, capacity, locality, idle) + protocoladapter/ Implements coordinator.Coordinator; mounts the /v0 wire + payment/ Stripe Connect: onboarding, charge, payout, webhook + identity/ SPIFFE integration, mTLS config, SPIFFE-binding middleware + store/ PostgreSQL pool + migrations + agent/ portal/ Transitional front-end-owned capabilities (see note above) +web/ Server-rendered templates + CSS +deploy/ Compose stack, SPIRE config, backup + deploy scripts +docs/ Architecture, operations, and session records +``` + +--- + +## Compilación + +Requisitos previos: Go 1.24+, una instancia de PostgreSQL 16 + TimescaleDB y Docker +(para el stack completo). + +```bash +git clone https://github.com/NTARI-RAND/SoHoLINK +cd SoHoLINK + +# Build the coordinator and portal binaries +go build ./cmd/orchestrator +go build ./cmd/portal + +# Run tests (unit) +go test ./... + +# Run integration tests against an isolated test database +# (DB name MUST contain "test" — fixtures refuse to touch any other database) +TEST_DATABASE_URL="postgres://postgres:changeme@localhost:5432/soholink_test?sslmode=disable" \ + go test -tags integration ./... +``` + +Las migraciones de la base de datos se aplican al arrancar el servicio (golang-migrate, +idempotentes). El stack completo de producción — Postgres, SPIRE, orquestador, portal, +ingress — se ejecuta mediante Docker Compose bajo `deploy/`. + +--- + +## Estado (honesto) + +- **Construido y en funcionamiento:** el reconocimiento de nodos, el emparejamiento y la + planificación, el ciclo de vida del empleo, la liquidación en moneda fiduciaria (Stripe + Connect), las declaraciones de tarifas firmadas por el coordinador, el cable de + coordinación `/v0`, la autenticación operador-o-SPIFFE y la identidad de carga de + trabajo SPIFFE están en producción en **[soholink.org](https://soholink.org)** (dominio + de confianza `spiffe://soholink.org`). +- **Despliegue de coordinador único.** La federación entre coordinadores y los puntos de + control atestiguados son un **objetivo de diseño, no algo construido** — el problema + abierto 7 de la arquitectura (el cómputo soberano compra una salida *mecánica*, no + *económica*) aplica en su totalidad y está nombrado, no resuelto. +- La **inscripción de operadores** (front end como operador) está verificada en pruebas, + pero no se ha completado de extremo a extremo en producción, a la espera del transporte + de correo de dos factores. +- **Todavía no hay nodos piloto en vivo.** El primer piloto apunta a una comunidad + residencial densa adyacente a la sede de NTARI. +- **La economía de miembros está deliberadamente en otro lugar** — el crédito, el pacto y + el registro viven en el front end (Cloudy), una capa más arriba. + +--- + +## Documentación + +| Documento | Descripción | +|---|---| +| [`CONFORMANCE.md`](CONFORMANCE.md) | Declaración del rol en términos de la JFA; vinculaciones de invariante a mecanismo; sustitutos nombrados | +| [`CLAUDE.md`](CLAUDE.md) | Contexto de ingeniería, convenciones y el historial de trabajo | +| `docs/` | Arquitectura, runbooks de operaciones y registros por sesión | + +El protocolo de coordinación compartido está especificado en el repositorio +[`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol) +(`SPEC.md`). + +--- + +## Licencia + +AGPL-3.0-or-later — véase [`LICENSE.txt`](LICENSE.txt). La AGPL mantiene todo el sustrato +como un bien común permanente: léalo, reimpleméntelo, bifúrquelo (fork), váyase. + +*Network Theory Applied Research Institute, Inc. — 501(c)(3) — EIN 92-3047136 — info@ntari.org* diff --git a/README.fr.md b/README.fr.md new file mode 100644 index 0000000..581cb0a --- /dev/null +++ b/README.fr.md @@ -0,0 +1,207 @@ +# SoHoLINK + +> Traduction communautaire (version préliminaire) — politique NTARI P2-002, Diffusion multilingue mondiale. Source : README.md (original anglais, instantané du 2026-07-29). Brouillon communautaire assisté par machine, en attente de relecture par le mainteneur régional conformément à P2-002 §3.1. Les spécifications techniques de référence restent en anglais conformément au §2.2. +> +> Vous avez remarqué une erreur de traduction ? N'hésitez pas à la corriger +> vous-même : forkez le dépôt https://github.com/NTARI-RAND/SoHoLINK et ouvrez +> une pull request. Les corrections de traduction sont des contributions +> précieuses, tout autant que le code. + +[![Version de Go](https://img.shields.io/badge/Go-1.24%2B-blue.svg)](https://golang.org) +[![Licence](https://img.shields.io/badge/License-AGPL%203.0-blue.svg)](LICENSE.txt) +[![CI](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml/badge.svg)](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml) + +**Le coordinateur de référence du substrat de calcul SoHoLINK / Cloudy.** SoHoLINK +transforme la capacité inutilisée de calcul, de stockage et d'impression des machines +détenues par les participants en une place de marché coordonnée : les membres +contribuent du matériel via un front end et perçoivent des paiements réels (en monnaie +fiat) ; d'autres membres achètent à la demande de la capacité de calcul, de stockage, +d'impression et de CDN. + +> **Le rôle, en une ligne :** SoHoLINK est le **coordinateur** — il orchestre le travail +> entre les nœuds et le règle. Ce n'est **pas** l'économie des membres, et c'est une +> pièce **remplaçable**. Voir [`CONFORMANCE.md`](CONFORMANCE.md) pour la déclaration +> de rôle complète, exprimée dans les termes propres à l'architecture. + +--- + +## Ce qu'est SoHoLINK + +SoHoLINK assure l'**orchestration côté nœud** pour un substrat Janus-Facing Architecture +(JFA) : + +- **Reconnaissance des nœuds** — les nœuds annoncent le travail qu'ils accepteront via des listes de capacités signées. +- **Appariement et ordonnancement** — placement des charges de travail sur les nœuds (en tenant compte de la localité, de l'inactivité et du retrait volontaire). +- **Cycle de vie de l'emploi** — offre → acceptation/refus → exécution → rapport → règlement, avec une fenêtre de contestation. +- **Déclarations de frais** — les frais n'existent que sous forme de messages signés par le coordinateur, lisibles et contestables. +- **Règlement en monnaie fiat** — versements aux contributeurs via Stripe Connect. +- **Fédération des front ends** — un objectif de conception (voir *État d'avancement* ci-dessous), pas encore réalisé. + +Le coordinateur est un **rôle enfichable et remplaçable.** Toute implémentation conforme +peut le remplacer, et un front end peut faire tourner son propre coordinateur ou apparier +directement les nœuds. Rien dans le réseau n'est obligé de passer par ce coordinateur en +particulier — c'est cette absence de privilège qui empêche un coordinateur de devenir un +pôle central impossible à retirer. + +## Ce que SoHoLINK n'est *pas* + +- **Pas l'économie des membres JFA.** Aucun crédit émis par les membres, aucun pacte de + réputation, aucun registre scellé par le dialogue, aucun arbitrage des litiges côté + membre. Tout cela vit dans le **front end** (Cloudy), par règle architecturale. +- **Aucun token, aucun portefeuille.** Le règlement se fait uniquement en monnaie fiat via + Stripe Connect, strictement séparé du crédit membre de tout front end. +- **Aucune personne sur le fil réseau.** Les contreparties de SoHoLINK sont des front ends + et des nœuds ; la seule identité qu'il manipule est l'identité de charge de travail (un + `NodeID` doté d'une liaison SPIFFE). L'identité des membres, le crédit, la réputation et + les données personnelles (PII) relèvent du front end. + +> **Surfaces transitoires.** L'agent de nœud (`internal/agent`, `cmd/agent`), le portail +> des membres (`internal/portal`, `cmd/portal`, `web/`) et la table `participants` sont des +> capacités appartenant au front end, actuellement hébergées dans ce dépôt, héritées de +> l'époque du double rôle de SoHoLINK. Elles sont maintenues en état de marche et étiquetées +> comme transitoires, en attente de migration vers le front end. Ne les considérez pas comme +> le rôle à long terme du coordinateur. + +--- + +## Sa place dans la pile + +``` +Front end (Cloudy) ──┐ + ├──► sohocloud-protocol (the dependency leaf: coordination only) +Coordinator (this) ──┘ +``` + +- SoHoLINK **consomme [`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol)** + à une version publiée (tag) — le module de coordination « taille fine » (thin waist) qu'il partage avec le front end. +- Il **expose le fil `/v0` du protocole** en parallèle de ses propres routes HTTP existantes, + de sorte qu'un front end conforme lui parle via le protocole standard pendant que les + routes transitoires continuent de fonctionner. +- Il ne dépend d'**aucun** front end ni d'**aucun** code de l'économie des membres. L'économie + des membres vit au-dessus de cette couche et ne doit jamais descendre dedans. + +--- + +## Invariants JFA que ce dépôt respecte + +| Invariant | Comment il est respecté ici | +|---|---| +| Les personnes n'apparaissent jamais sur le fil réseau | Les contreparties sont des front ends et des nœuds ; l'identité sur le fil est un `NodeID` SPIFFE | +| Identité de participant unique | Une seule table `participants` — aucune séparation fournisseur/consommateur dans le schéma ni dans le code | +| Lisibilité des frais | Les frais n'existent que sous forme de messages `FeeDeclaration` signés par le coordinateur | +| Le fiat reste fiat ; le crédit reste chez lui | Le règlement se fait uniquement via Stripe Connect ; strictement séparé du crédit membre | +| Aucune asymétrie d'information | La tarification, le comptage et les gains sont visibles pour les participants | +| Surface de gouvernance séparée | L'administration et la gouvernance tournent sur une interface distincte, accessible en local uniquement — jamais sur le site public, jamais derrière des indicateurs de rôle | +| Provenance entrante = sortante | AGPL-3.0 ; signature DCO ; pas de CLA | + +--- + +## Pile technologique + +| Couche | Technologie | +|---|---| +| Langage | Go 1.24+ | +| Web | HTML rendu côté serveur avec `html/template` de Go — aucun framework JS, aucune étape de build (doit fonctionner sur un téléphone Android de 2019 en 3G et dans les navigateurs de Smart TV) | +| Base de données | PostgreSQL 16 + TimescaleDB, `pgx/v5` (sans ORM) | +| Stockage objet | MinIO (compatible S3) | +| Identité | SPIFFE/SPIRE — mTLS, SVID X.509 à durée de vie courte | +| Paiements | Stripe Connect (monnaie fiat uniquement) | +| Déploiement | Docker Compose derrière un tunnel Cloudflare | +| CI | GitHub Actions | + +--- + +## Structure du dépôt + +``` +cmd/ + orchestrator/ Coordinator service: matching, employment lifecycle, /v0 wire, settlement hooks + portal/ Member portal (transitional, front-end-owned) + agent/ Node agent (transitional, front-end-owned) + seed/ Dev/load-test seeder — never point at production +internal/ + api/ Control-plane HTTP API (+ protocol /v0 handlers via protocoladapter) + orchestrator/ Node registry, matching, placement scoring, job token issuance + scheduler/ Scoring-based placement (class, freshness, capacity, locality, idle) + protocoladapter/ Implements coordinator.Coordinator; mounts the /v0 wire + payment/ Stripe Connect: onboarding, charge, payout, webhook + identity/ SPIFFE integration, mTLS config, SPIFFE-binding middleware + store/ PostgreSQL pool + migrations + agent/ portal/ Transitional front-end-owned capabilities (see note above) +web/ Server-rendered templates + CSS +deploy/ Compose stack, SPIRE config, backup + deploy scripts +docs/ Architecture, operations, and session records +``` + +--- + +## Build + +Prérequis : Go 1.24+, une instance PostgreSQL 16 + TimescaleDB et Docker (pour la pile +complète). + +```bash +git clone https://github.com/NTARI-RAND/SoHoLINK +cd SoHoLINK + +# Build the coordinator and portal binaries +go build ./cmd/orchestrator +go build ./cmd/portal + +# Run tests (unit) +go test ./... + +# Run integration tests against an isolated test database +# (DB name MUST contain "test" — fixtures refuse to touch any other database) +TEST_DATABASE_URL="postgres://postgres:changeme@localhost:5432/soholink_test?sslmode=disable" \ + go test -tags integration ./... +``` + +Les migrations de base de données sont appliquées au démarrage du service (golang-migrate, +idempotent). La pile de production complète — Postgres, SPIRE, orchestrator, portal, +ingress — s'exécute via Docker Compose sous `deploy/`. + +--- + +## État d'avancement (en toute franchise) + +- **Réalisé et en fonctionnement :** la reconnaissance des nœuds, l'appariement et + l'ordonnancement, le cycle de vie de l'emploi, le règlement en monnaie fiat (Stripe + Connect), les déclarations de frais signées par le coordinateur, le fil de coordination + `/v0`, l'authentification par opérateur ou SPIFFE et l'identité de charge de travail + SPIFFE sont en production sur **[soholink.org](https://soholink.org)** (domaine de + confiance `spiffe://soholink.org`). +- **Déploiement à coordinateur unique.** La fédération entre coordinateurs et les points de + contrôle attestés sont un **objectif de conception, pas une réalisation** — le problème + ouvert n° 7 de l'architecture (le calcul souverain achète une sortie *mécanique*, et non + *économique*) s'applique pleinement ; il est nommé, non résolu. +- **L'inscription des opérateurs** (front end en tant qu'opérateur) est vérifiée par les + tests mais n'a pas encore abouti de bout en bout en production, en attente du transport de + courrier à deux facteurs. +- **Aucun nœud pilote en service pour l'instant.** Le premier pilote visera une communauté + résidentielle dense adjacente au siège de NTARI. +- **L'économie des membres est délibérément ailleurs** — le crédit, le pacte et le registre + vivent dans le front end (Cloudy), une couche plus haut. + +--- + +## Documentation + +| Document | Description | +|---|---| +| [`CONFORMANCE.md`](CONFORMANCE.md) | Déclaration de rôle en termes JFA ; correspondances entre invariants et mécanismes ; substituts nommés | +| [`CLAUDE.md`](CLAUDE.md) | Contexte d'ingénierie, conventions et historique de travail | +| `docs/` | Architecture, guides d'exploitation (runbooks) et comptes rendus par session | + +Le protocole de coordination partagé est spécifié dans le dépôt +[`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol) +(`SPEC.md`). + +--- + +## Licence + +AGPL-3.0-or-later — voir [`LICENSE.txt`](LICENSE.txt). L'AGPL fait de tout le substrat un +bien commun permanent : lisez-le, réimplémentez-le, forkez-le, partez. + +*Network Theory Applied Research Institute, Inc. — 501(c)(3) — EIN 92-3047136 — info@ntari.org* diff --git a/README.hi.md b/README.hi.md new file mode 100644 index 0000000..0b31105 --- /dev/null +++ b/README.hi.md @@ -0,0 +1,202 @@ +> सामुदायिक अनुवाद (मसौदा) — NTARI नीति P2-002, Global Multilingual Broadcast। स्रोत: README.md (अंग्रेज़ी मूल, स्नैपशॉट 2026-07-29)। P2-002 §3.1 के अनुसार क्षेत्रीय मेंटेनर की समीक्षा तक लंबित, मशीन-सहायता से तैयार सामुदायिक मसौदा। §2.2 के अनुसार मूल तकनीकी विनिर्देश अंग्रेज़ी में ही रहते हैं। +> +> अनुवाद में कोई त्रुटि दिखे तो कृपया उसे स्वयं सुधारने में मदद करें: +> रिपॉज़िटरी को फ़ॉर्क (fork) करें और अपना सुधार पुल रिक्वेस्ट (pull request) +> के रूप में भेजें — https://github.com/NTARI-RAND/SoHoLINK। अनुवाद-सुधार +> हमारे लिए किसी भी अन्य योगदान जितने ही मूल्यवान हैं, और उनका सदा स्वागत है। + +# SoHoLINK + +[![Go संस्करण](https://img.shields.io/badge/Go-1.24%2B-blue.svg)](https://golang.org) +[![लाइसेंस](https://img.shields.io/badge/License-AGPL%203.0-blue.svg)](LICENSE.txt) +[![CI](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml/badge.svg)](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml) + +**SoHoLINK / Cloudy कंप्यूट सब्सट्रेट का संदर्भ (reference) कोऑर्डिनेटर।** SoHoLINK +प्रतिभागियों के स्वामित्व वाली मशीनों की निष्क्रिय (idle) कंप्यूट, स्टोरेज और प्रिंट क्षमता को +एक समन्वित मार्केटप्लेस में बदल देता है: सदस्य एक फ्रंट एंड के माध्यम से हार्डवेयर का योगदान +करते हैं और वास्तविक (फ़िएट) भुगतान कमाते हैं; अन्य सदस्य माँग पर कंप्यूट, स्टोरेज, प्रिंट और +CDN क्षमता खरीदते हैं। + +> **भूमिका, एक पंक्ति में:** SoHoLINK **कोऑर्डिनेटर** है — यह नोड्स के बीच काम का +> ऑर्केस्ट्रेशन करता है और उसका निपटान (settle) करता है। यह सदस्य अर्थव्यवस्था **नहीं** है, +> और यह एक **प्रतिस्थापन-योग्य** हिस्सा है। आर्किटेक्चर की अपनी शब्दावली में पूर्ण +> भूमिका-घोषणा के लिए [`CONFORMANCE.md`](CONFORMANCE.md) देखें। + +--- + +## SoHoLINK क्या है + +SoHoLINK एक Janus-Facing Architecture (JFA) सब्सट्रेट के लिए **नोड-पक्षीय ऑर्केस्ट्रेशन** +करता है: + +- **नोड पहचान (recognition)** — नोड्स हस्ताक्षरित क्षमता-सूचियों (signed capability listings) के माध्यम से घोषित करते हैं कि वे कौन-सा काम करेंगे। +- **मैचिंग और शेड्यूलिंग** — वर्कलोड को नोड्स पर रखना (locality-aware, idle-aware, opt-out का सम्मान करने वाला)। +- **रोज़गार जीवनचक्र** — प्रस्ताव → स्वीकार/अस्वीकार → निष्पादन → रिपोर्ट → निपटान, एक विवाद-विंडो के साथ। +- **शुल्क घोषणाएँ** — शुल्क केवल कोऑर्डिनेटर-हस्ताक्षरित, सुपाठ्य, चुनौती-योग्य संदेशों के रूप में ही मौजूद होते हैं। +- **फ़िएट निपटान** — Stripe Connect के माध्यम से योगदानकर्ताओं को भुगतान। +- **फ्रंट एंड्स का फ़ेडरेशन** — एक डिज़ाइन लक्ष्य (नीचे *स्थिति* देखें), अभी निर्मित नहीं। + +कोऑर्डिनेटर एक **प्लग करने योग्य, प्रतिस्थापन-योग्य भूमिका है।** कोई भी अनुरूप (conformant) +कार्यान्वयन इसकी जगह ले सकता है, और कोई फ्रंट एंड अपना स्वयं का कोऑर्डिनेटर चला सकता है +या सीधे नोड्स से मैच कर सकता है। नेटवर्क में किसी भी चीज़ के लिए इसी विशेष कोऑर्डिनेटर से +होकर गुज़रना अनिवार्य नहीं है — यही गैर-विशेषाधिकार किसी कोऑर्डिनेटर को एक अहटाए-न-जा-सकने +वाला केंद्र (hub) बनने से रोकता है। + +## SoHoLINK क्या *नहीं* है + +- **JFA सदस्य अर्थव्यवस्था नहीं।** कोई सदस्य-जारी क्रेडिट नहीं, कोई प्रतिष्ठा अनुबंध + (reputation covenant) नहीं, कोई डायलॉग-सील्ड रिकॉर्ड नहीं, कोई सदस्य-सम्मुख विवाद-निर्णय + नहीं। ये सब, आर्किटेक्चर के नियम से, **फ्रंट एंड** (Cloudy) में रहते हैं। +- **कोई टोकन नहीं, कोई वॉलेट नहीं।** निपटान Stripe Connect के माध्यम से विशुद्ध फ़िएट है, + जिसे किसी भी फ्रंट एंड के सदस्य-क्रेडिट से सख़्ती से अलग रखा जाता है। +- **वायर पर कोई व्यक्ति नहीं।** SoHoLINK के प्रतिपक्ष (counterparties) फ्रंट एंड और नोड्स + हैं; यह जिस एकमात्र पहचान को संभालता है वह वर्कलोड-पहचान है (SPIFFE बाइंडिंग वाला एक + `NodeID`)। सदस्य-पहचान, क्रेडिट, प्रतिष्ठा और PII फ्रंट-एंड के सरोकार हैं। + +> **संक्रमणकालीन सतहें।** नोड एजेंट (`internal/agent`, `cmd/agent`), सदस्य पोर्टल +> (`internal/portal`, `cmd/portal`, `web/`), और `participants` तालिका फ्रंट-एंड के +> स्वामित्व वाली क्षमताएँ हैं, जो SoHoLINK के पहले के दोहरी-भूमिका दौर से फ़िलहाल इसी +> रिपॉज़िटरी में होस्ट की जा रही हैं। इन्हें चालू हालत में रखा गया है और संक्रमणकालीन के रूप +> में लेबल किया गया है; फ्रंट एंड में माइग्रेशन लंबित है। इन्हें कोऑर्डिनेटर की दीर्घकालिक +> भूमिका न मानें। + +--- + +## स्टैक में यह कहाँ बैठता है + +``` +Front end (Cloudy) ──┐ + ├──► sohocloud-protocol (the dependency leaf: coordination only) +Coordinator (this) ──┘ +``` + +- SoHoLINK एक प्रकाशित संस्करण-टैग पर **[`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol) + का उपभोग करता है** — वह thin-waist समन्वय मॉड्यूल जिसे यह फ्रंट एंड के साथ साझा करता है। +- यह अपने मौजूदा HTTP रूट्स के साथ-साथ **प्रोटोकॉल का `/v0` वायर सर्व करता है**, ताकि कोई + अनुरूप फ्रंट एंड मानक प्रोटोकॉल पर इससे संवाद कर सके और संक्रमणकालीन रूट्स भी काम + करती रहें। +- यह **किसी भी** फ्रंट एंड और **किसी भी** सदस्य-अर्थव्यवस्था कोड पर निर्भर नहीं है। सदस्य + अर्थव्यवस्था इस परत के ऊपर रहती है और उसे कभी भी नीचे इस परत में नहीं उतरना चाहिए। + +--- + +## JFA इनवैरिएंट जिनका यह रिपॉज़िटरी पालन करती है + +| इनवैरिएंट | यहाँ इसे कैसे पूरा किया गया है | +|---|---| +| व्यक्ति कभी वायर पर नहीं आते | प्रतिपक्ष फ्रंट एंड और नोड्स हैं; वायर-पहचान एक SPIFFE `NodeID` है | +| एकल प्रतिभागी-पहचान | एक ही `participants` तालिका — स्कीमा या कोड में प्रदाता/उपभोक्ता का कोई विभाजन नहीं | +| शुल्क की सुपाठ्यता | शुल्क केवल कोऑर्डिनेटर-हस्ताक्षरित `FeeDeclaration` संदेशों के रूप में मौजूद हैं | +| फ़िएट फ़िएट रहता है; क्रेडिट अपने घर में रहता है | निपटान विशुद्ध Stripe Connect है; सदस्य-क्रेडिट से सख़्ती से अलग | +| कोई सूचना-विषमता नहीं | मूल्य-निर्धारण, मीटरिंग और कमाई प्रतिभागियों को दिखाई देती है | +| गवर्नेंस सतह पृथक है | एडमिन/गवर्नेंस एक अलग, केवल-लोकल इंटरफ़ेस पर चलता है — कभी सार्वजनिक साइट पर नहीं, कभी role flags के पीछे नहीं | +| प्रोवेनेंस इनबाउंड = आउटबाउंड | AGPL-3.0; DCO साइन-ऑफ़; कोई CLA नहीं | + +--- + +## टेक्नोलॉजी स्टैक + +| परत | टेक्नोलॉजी | +|---|---| +| भाषा | Go 1.24+ | +| वेब | Go `html/template` के माध्यम से सर्वर-रेंडर्ड HTML — कोई JS फ्रेमवर्क नहीं, कोई बिल्ड-स्टेप नहीं (3G पर 2019 के Android फ़ोन और Smart TV ब्राउज़रों में काम करना अनिवार्य है) | +| डेटाबेस | PostgreSQL 16 + TimescaleDB, `pgx/v5` (कोई ORM नहीं) | +| ऑब्जेक्ट स्टोरेज | MinIO (S3-संगत) | +| पहचान (Identity) | SPIFFE/SPIRE — mTLS, अल्पजीवी X.509 SVIDs | +| भुगतान | Stripe Connect (केवल फ़िएट) | +| डिप्लॉय | Cloudflare टनल के पीछे Docker Compose | +| CI | GitHub Actions | + +--- + +## रिपॉज़िटरी संरचना + +``` +cmd/ + orchestrator/ Coordinator service: matching, employment lifecycle, /v0 wire, settlement hooks + portal/ Member portal (transitional, front-end-owned) + agent/ Node agent (transitional, front-end-owned) + seed/ Dev/load-test seeder — never point at production +internal/ + api/ Control-plane HTTP API (+ protocol /v0 handlers via protocoladapter) + orchestrator/ Node registry, matching, placement scoring, job token issuance + scheduler/ Scoring-based placement (class, freshness, capacity, locality, idle) + protocoladapter/ Implements coordinator.Coordinator; mounts the /v0 wire + payment/ Stripe Connect: onboarding, charge, payout, webhook + identity/ SPIFFE integration, mTLS config, SPIFFE-binding middleware + store/ PostgreSQL pool + migrations + agent/ portal/ Transitional front-end-owned capabilities (see note above) +web/ Server-rendered templates + CSS +deploy/ Compose stack, SPIRE config, backup + deploy scripts +docs/ Architecture, operations, and session records +``` + +--- + +## बिल्ड + +पूर्वापेक्षाएँ: Go 1.24+, एक PostgreSQL 16 + TimescaleDB इंस्टेंस, और Docker (पूरे स्टैक +के लिए)। + +```bash +git clone https://github.com/NTARI-RAND/SoHoLINK +cd SoHoLINK + +# Build the coordinator and portal binaries +go build ./cmd/orchestrator +go build ./cmd/portal + +# Run tests (unit) +go test ./... + +# Run integration tests against an isolated test database +# (DB name MUST contain "test" — fixtures refuse to touch any other database) +TEST_DATABASE_URL="postgres://postgres:changeme@localhost:5432/soholink_test?sslmode=disable" \ + go test -tags integration ./... +``` + +डेटाबेस माइग्रेशन सेवा के स्टार्टअप पर लागू किए जाते हैं (golang-migrate, idempotent)। +पूरा प्रोडक्शन स्टैक — Postgres, SPIRE, orchestrator, portal, ingress — `deploy/` के +अंतर्गत Docker Compose के माध्यम से चलता है। + +--- + +## स्थिति (ईमानदार आकलन) + +- **निर्मित और चालू:** नोड पहचान, मैचिंग/शेड्यूलिंग, रोज़गार जीवनचक्र, फ़िएट निपटान + (Stripe Connect), कोऑर्डिनेटर-हस्ताक्षरित शुल्क-घोषणाएँ, `/v0` समन्वय-वायर, + ऑपरेटर-या-SPIFFE प्रमाणीकरण, और SPIFFE वर्कलोड-पहचान — ये सब + **[soholink.org](https://soholink.org)** पर प्रोडक्शन में लाइव हैं (trust domain + `spiffe://soholink.org`)। +- **एकल-कोऑर्डिनेटर डिप्लॉयमेंट।** क्रॉस-कोऑर्डिनेटर फ़ेडरेशन और साक्षी-सत्यापित + चेकपॉइंट (witnessed checkpoints) एक **डिज़ाइन लक्ष्य हैं, बने नहीं हैं** — आर्किटेक्चर + की खुली समस्या 7 (सॉवरेन कंप्यूट *यांत्रिक* निकास खरीदता है, *आर्थिक* नहीं) पूरी तरह + लागू होती है और उसे नाम दिया गया है, हल नहीं किया गया। +- **ऑपरेटर नामांकन** (front-end-as-operator) परीक्षणों में सत्यापित है लेकिन प्रोडक्शन में + एंड-टू-एंड पूरा नहीं हुआ है; दो-कारक (two-factor) मेल ट्रांसपोर्ट लंबित है। +- **अभी कोई लाइव पायलट नोड नहीं।** पहला पायलट NTARI के मुख्यालय से सटे एक घने + आवासीय समुदाय को लक्षित करता है। +- **सदस्य अर्थव्यवस्था जान-बूझकर कहीं और है** — क्रेडिट, अनुबंध (covenant) और रिकॉर्ड + एक परत ऊपर, फ्रंट एंड (Cloudy) में रहते हैं। + +--- + +## दस्तावेज़ीकरण + +| दस्तावेज़ | विवरण | +|---|---| +| [`CONFORMANCE.md`](CONFORMANCE.md) | JFA शब्दावली में भूमिका-घोषणा; इनवैरिएंट-से-तंत्र बाइंडिंग; नामित स्टैंड-इन | +| [`CLAUDE.md`](CLAUDE.md) | इंजीनियरिंग संदर्भ, परिपाटियाँ, और कार्य-इतिहास | +| `docs/` | आर्किटेक्चर, ऑपरेशन रनबुक, और प्रति-सत्र रिकॉर्ड | + +साझा समन्वय प्रोटोकॉल [`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol) +रिपॉज़िटरी (`SPEC.md`) में विनिर्दिष्ट है। + +--- + +## लाइसेंस + +AGPL-3.0-or-later — देखें [`LICENSE.txt`](LICENSE.txt)। AGPL पूरे सब्सट्रेट को एक स्थायी +कॉमन्स बनाए रखता है: इसे पढ़ें, फिर से कार्यान्वित करें, फ़ोर्क करें, छोड़ कर जाएँ। + +*Network Theory Applied Research Institute, Inc. — 501(c)(3) — EIN 92-3047136 — info@ntari.org* diff --git a/README.md b/README.md index 0ae9260..e18dbd4 100644 --- a/README.md +++ b/README.md @@ -1,214 +1,174 @@ -# SoHoLINK — Federated SOHO Compute Marketplace +# SoHoLINK -[![Go Version](https://img.shields.io/badge/Go-1.25.7-blue.svg)](https://golang.org) +[![Go Version](https://img.shields.io/badge/Go-1.24%2B-blue.svg)](https://golang.org) [![License](https://img.shields.io/badge/License-AGPL%203.0-blue.svg)](LICENSE.txt) [![CI](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml/badge.svg)](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml) -**Aggregate the idle compute power in your home or office. Earn real payments for sharing what you already own.** +**The reference coordinator of the SoHoLINK / Cloudy compute substrate.** SoHoLINK +turns the idle compute, storage, and print capacity of participant-owned machines +into a coordinated marketplace: members contribute hardware through a front end and +earn real (fiat) payments; other members buy compute, storage, print, and CDN +capacity on demand. -SoHoLINK is a federated compute marketplace for Small Office/Home Office (SOHO) hardware. It turns underutilized desktops, NAS devices, mini-PCs, and mobile devices into income-generating compute nodes — connected through a Kubernetes-inspired scheduler, settled via Stripe and Lightning, and governed by Open Policy Agent rules the provider fully controls. +> **Role, in one line:** SoHoLINK is the **coordinator** — it orchestrates work +> across nodes and settles it. It is **not** the member economy, and it is a +> **replaceable** part. See [`CONFORMANCE.md`](CONFORMANCE.md) for the full +> role declaration in the architecture's own terms. --- -## What It Does +## What SoHoLINK is -| For Providers | For Requesters | -|---|---| -| Earn per hour of CPU/storage contributed | Browse available SOHO compute nodes — filter by CPU, region, GPU, price, reputation | -| Set pricing and resource limits in a wizard | Top up a prepaid satoshi wallet via Lightning invoice or Stripe | -| Accept or auto-accept rental requests via OPA policy | Get instant cost estimates in sats and USD before committing | -| Watch earnings accumulate in real time on the dashboard | Launch workloads in one API call — wallet debited + workload submitted atomically | -| Visualize the network on a 3D globe | Track and cancel orders; proportional refund for unused time | +SoHoLINK performs **node-side orchestration** for a Janus-Facing Architecture (JFA) +substrate: ---- +- **Node recognition** — nodes advertise what work they will do via signed capability listings. +- **Matching & scheduling** — placement of workloads onto nodes (locality-aware, idle-aware, opt-out-respecting). +- **Employment lifecycle** — offer → accept/decline → run → report → settle, with a dispute window. +- **Fee declarations** — fees exist only as coordinator-signed, legible, contestable messages. +- **Fiat settlement** — payouts to contributors via Stripe Connect. +- **Federation of front ends** — a design target (see *Status* below), not yet built. -## Features - -- **Hardware Discovery** — Detects CPU, GPU, RAM, storage, and network across Windows, Linux, and macOS at startup; computes a fair per-hour provider rate automatically -- **Federated Scheduler (FedScheduler)** — Kubernetes-inspired workload placement across independent SOHO nodes; supports placement constraints, auto-scaling, and health monitoring -- **IPFS Storage Pool** — Content-addressed data movement via a local Kubo daemon; inputs pinned as CIDs, outputs returned as CIDs, no central file server -- **Dual-Rail Payments** — Stripe for card payments; Lightning Network for sub-cent micropayments; 1% platform fee, ~97% payout to providers -- **OPA Policy Governance** — Providers express resource-sharing rules in Rego (max CPU share, bandwidth limits, requester reputation thresholds); auto-accept engine enforces them -- **Per-Hour Metering** — Billing loop charges requesters per hour of actual usage; `FedScheduler` feeds live placement data to the `UsageMeter` goroutine; Lightning hold invoices (HTLC) release payment only after result verification; provider payouts via `POST /api/revenue/request-payout` with full history at `GET /api/revenue/payouts` -- **ML-Driven Scheduling** — `LinUCBBandit` contextual bandit replaces round-robin node selection in `ScheduleMobile`; per-node UCB scores learned from HTLC settle/cancel outcomes; `TelemetryRecorder` streams JSONL dispatch events to disk for offline training; falls back to uniform random if no bandit is wired -- **Setup Wizard (8 steps)** — Guided onboarding: hardware review → pricing → network → payments → K8s edges → IPFS → provisioning limits → policies -- **Dashboard (8 tabs)** — Overview, Hardware, Orchestration, Storage, Billing, Users, Policies, Logs; all live data, no page refresh needed -- **Federation & Marketplace Settings** — Dedicated settings dialog (Settings → Federation & Marketplace…) covers coordinator role, fee %, coordinator URL, region, CPU-hour pricing, and heartbeat interval; supports both private cooperative groups and open-marketplace participation from the same UI -- **3D Globe Visualization** — WebSocket-connected Three.js globe; topology mode and geographic mode (real lat/lon from node metadata); animated data flow arcs -- **Zero-Dependency Installers** — Statically linked Windows `.exe` + NSIS setup wizard; macOS universal `.pkg`; Linux `.deb`, `.rpm`, AppImage — produced by GoReleaser in one command -- **P2P LAN Mesh Discovery** — Nodes on the same network automatically find each other via Ed25519-signed multicast UDP announcements (group `239.255.42.99:7946`; RFC 2365, stays on LAN); discovered peers instantly visible to the scheduler and accessible via `GET /api/peers`; topology follows the Watts–Strogatz small-world model — dense local clusters, short global paths -- **Buyer-Side Marketplace** — Full requester experience: browse provider nodes (filter by CPU, region, GPU, price, reputation); get real-time cost estimates in sats + USD; top up a prepaid satoshi wallet via Lightning or Stripe; purchase and launch workloads in a single atomic call; track and cancel orders with proportional refund — all from REST API or Flutter app -- **Mobile Participation** *(Go prerequisites complete; native apps in development)* — Android TV always-on compute node; Android "Earn While Charging" client; iOS monitoring and management app +The coordinator is a **pluggable, replaceable role.** Any conformant implementation +may replace it, and a front end may run its own coordinator or match directly against +nodes. Nothing in the network is required to route through this particular coordinator — +that non-privilege is what keeps a coordinator from becoming an unremovable hub. ---- +## What SoHoLINK is *not* -## Quick Start +- **Not the JFA member economy.** No member-issued credit, no reputation covenant, no + dialog-sealed record, no member-facing dispute adjudication. Those live in the **front + end** (Cloudy), by architectural rule. +- **No tokens, no wallets.** Settlement is pure fiat via Stripe Connect, kept strictly + separate from any front end's member credit. +- **No persons on the wire.** SoHoLINK's counterparties are front ends and nodes; the + only identity it handles is workload identity (a `NodeID` with a SPIFFE binding). + Member identity, credit, reputation, and PII are front-end concerns. -### Download a Release (Recommended) +> **Transitional surfaces.** The node agent (`internal/agent`, `cmd/agent`), the member +> portal (`internal/portal`, `cmd/portal`, `web/`), and the `participants` table are +> front-end-owned capabilities currently hosted in this repo from SoHoLINK's earlier +> dual-role era. They are kept working and labeled as transitional, pending migration to +> the front end. Do not treat them as the coordinator's long-term role. -Go to [Releases](https://github.com/NTARI-RAND/SoHoLINK/releases) and download the installer for your platform: +--- -- **Windows:** `SoHoLINK-Setup.exe` (NSIS installer — no runtime dependencies) -- **macOS:** `SoHoLINK-*.pkg` (universal binary — Intel + Apple Silicon) -- **Linux:** `FedAAA-*-x86_64.AppImage` or `.deb` / `.rpm` +## Where it sits in the stack -### Build from Source +``` +Front end (Cloudy) ──┐ + ├──► sohocloud-protocol (the dependency leaf: coordination only) +Coordinator (this) ──┘ +``` -```bash -# Prerequisites: Go 1.24.6, GCC/MinGW (for GUI), git +- SoHoLINK **consumes [`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol)** + at a published version tag — the thin-waist coordination module it shares with the front end. +- It **serves the protocol's `/v0` wire** alongside its own existing HTTP routes, so a + conformant front end talks to it over the standard protocol while transitional routes + keep working. +- It depends on **no** front end and **no** member-economy code. The member economy lives + above this layer and must never migrate down into it. -# Clone -git clone https://github.com/NTARI-RAND/SoHoLINK -cd soholink +--- -# Build headless CLI (no CGO required) -make build-cli +## JFA invariants this repo holds -# Build GUI (requires CGO + GCC; on Windows: MinGW via winget install msys2) -make build-gui +| Invariant | How it is met here | +|---|---| +| Persons never appear on the wire | Counterparties are front ends and nodes; wire identity is a SPIFFE `NodeID` | +| Single participant identity | One `participants` table — no provider/consumer split in schema or code | +| Fee legibility | Fees exist only as coordinator-signed `FeeDeclaration` messages | +| Fiat stays fiat; credit stays home | Settlement is pure Stripe Connect; strictly separate from member credit | +| No information asymmetry | Pricing, metering, and earnings are visible to participants | +| Governance surface separated | Admin/governance runs on a separate, local-only interface — never on the public site, never behind role flags | +| Provenance inbound = outbound | AGPL-3.0; DCO sign-off; no CLA | -# Run setup wizard (first launch) -./bin/soholink +--- -# All-platform release packages (requires goreleaser) -make dist -``` +## Technology stack -> **Windows GUI note:** Fyne requires CGO + MinGW. -> `winget install msys2` → open MSYS2 terminal → `pacman -S mingw-w64-x86_64-gcc` -> Add `C:\msys64\mingw64\bin` to your PATH, then `make build-gui`. +| Layer | Technology | +|---|---| +| Language | Go 1.24+ | +| Web | Server-rendered HTML via Go `html/template` — no JS framework, no build step (must work on a 2019 Android phone on 3G and in Smart TV browsers) | +| Database | PostgreSQL 16 + TimescaleDB, `pgx/v5` (no ORM) | +| Object storage | MinIO (S3-compatible) | +| Identity | SPIFFE/SPIRE — mTLS, short-lived X.509 SVIDs | +| Payments | Stripe Connect (fiat only) | +| Deploy | Docker Compose behind a Cloudflare tunnel | +| CI | GitHub Actions | --- -## Architecture Overview +## Repository structure ``` - ┌──────────────────────────────────────┐ - │ SoHoLINK Node (SOHO) │ - │ │ - Requester │ ┌─────────────┐ ┌──────────────┐ │ - (submits workload) ──►│ │ FedScheduler│ │ HTTP API │ │ - │ │ (Go) │ │ (REST) │ │ - │ └──────┬──────┘ └──────────────┘ │ - │ │ │ - │ ┌──────▼──────────────────────┐ │ - │ │ OPA Policies │ │ - │ │ (resource_sharing.rego) │ │ - │ └──────┬──────────────────────┘ │ - │ │ │ - │ ┌──────▼──────┐ ┌──────────────┐ │ - │ │ IPFS Pool │ │ Payment │ │ - │ │ (storage) │ │ Stripe/LN │ │ - │ └─────────────┘ └──────────────┘ │ - │ │ - │ ┌────────────────────────────────┐ │ - │ │ Fyne GUI Dashboard │ │ - │ │ + 3D Globe (WebSocket) │ │ - │ └────────────────────────────────┘ │ - └──────────────────────────────────────┘ - │ - Federation (WebSocket/P2P) - │ - ┌──────────────────────────┼──────────────────────────┐ - │ │ │ - ┌──────────▼──────────┐ ┌──────────▼──────────┐ ┌──────────▼──────────┐ - │ SOHO Node (Linux) │ │ SOHO Node (macOS) │ │ Android TV Node │ - │ mini-PC / NAS │ │ iMac / MacBook │ │ (always-on mobile) │ - └─────────────────────┘ └─────────────────────┘ └─────────────────────┘ +cmd/ + orchestrator/ Coordinator service: matching, employment lifecycle, /v0 wire, settlement hooks + portal/ Member portal (transitional, front-end-owned) + agent/ Node agent (transitional, front-end-owned) + seed/ Dev/load-test seeder — never point at production +internal/ + api/ Control-plane HTTP API (+ protocol /v0 handlers via protocoladapter) + orchestrator/ Node registry, matching, placement scoring, job token issuance + scheduler/ Scoring-based placement (class, freshness, capacity, locality, idle) + protocoladapter/ Implements coordinator.Coordinator; mounts the /v0 wire + payment/ Stripe Connect: onboarding, charge, payout, webhook + identity/ SPIFFE integration, mTLS config, SPIFFE-binding middleware + store/ PostgreSQL pool + migrations + agent/ portal/ Transitional front-end-owned capabilities (see note above) +web/ Server-rendered templates + CSS +deploy/ Compose stack, SPIRE config, backup + deploy scripts +docs/ Architecture, operations, and session records ``` -### Key Subsystems - -| Package | Role | -|---|---| -| `internal/p2p/` | Small-world LAN mesh: signed multicast UDP discovery, Ed25519 peer auth, `/api/peers` | -| `internal/orchestration/` | FedScheduler, auto-scaler, node discovery, mobile scheduling, K8s edge adapter | -| `internal/ml/` | Pure-Go ML primitives: `LinUCBBandit`, `TelemetryRecorder`, dimension constants | -| `internal/httpapi/` | 46+ REST endpoints + WebSocket hub; per-IP rate limiting; Ed25519 federation auth; marketplace + wallet handlers | -| `internal/storage/` | Local content-addressed pool + IPFS HTTP client (Kubo) | -| `internal/payment/` | Stripe + Lightning processors, HTLC hold invoices, metering loop, ledger, settler, payout system | -| `internal/notification/` | APNs push notification client (iOS — JWT auth, auto-refresh) | -| `internal/wasm/` | Wasm task executor interface + stub (wazero implementation: v0.3) | -| `internal/rental/` | Auto-accept engine for incoming resource requests | -| `internal/wizard/` | Hardware detection, cost calculator, pricing, policy config | -| `internal/gui/dashboard/` | Fyne dashboard (~1,750 lines): 8 tabs, 8 settings dialogs, 8-step wizard | -| `internal/central/` | 1% platform fee calculation and ledger recording | -| `internal/store/` | SQLite via `modernc.org/sqlite`; all persistent state | -| `internal/lbtas/` | Trust and reputation scoring | -| `internal/blockchain/` | Tamper-evident Merkle chain for accounting logs | -| `configs/policies/` | OPA Rego policies for resource sharing and governance | -| `ui/globe-interface/` | Three.js 3D globe, WebSocket bridge to DDS graph | - --- -## Node Participation Tiers - -SoHoLINK supports a spectrum of hardware from always-on servers to mobile devices: - -| Tier | Hardware | Role | Constraints | -|---|---|---|---| -| **Full** | Desktop, mini-PC, NAS, server | Compute worker + storage node + scheduler peer | None | -| **Partial** | Laptop | Compute worker when plugged in | Suspend awareness | -| **Headless mobile** | Android TV / Fire TV box | Compute worker (always-on, no battery) | ARM64 tasks | -| **Mobile (Android)** | Smartphone / tablet | Short-burst compute + storage relay | Plugged in + WiFi; tasks ≤120 s | -| **Monitoring (iOS)** | iPhone / iPad | Earnings dashboard + management client | No background compute | - -> See [`docs/MOBILE_INTEGRATION.md`](docs/MOBILE_INTEGRATION.md) for the full mobile participation roadmap. - ---- +## Build -## Build Targets +Prerequisites: Go 1.24+, a PostgreSQL 16 + TimescaleDB instance, and Docker (for the +full stack). -| Make target | Output | Notes | -|---|---|---| -| `make build-cli` | `bin/soholink` | Headless CLI, no CGO required | -| `make build-gui` | `bin/soholink-gui` | Full GUI, requires CGO + GCC | -| `make build-static-windows` | `bin/soholink.exe` | Statically linked, zero DLL deps | -| `make fyne-package-windows` | `SoHoLINK.exe` | Fyne-bundled with manifest + icon | -| `make dist` | `dist/` | All platforms via GoReleaser (snapshot) | -| `make dist-release` | `dist/` + GitHub Release | Requires `git tag v*` | -| `make test` | — | Race detector + coverage | -| `make help` | — | Full target reference | +```bash +git clone https://github.com/NTARI-RAND/SoHoLINK +cd SoHoLINK ---- +# Build the coordinator and portal binaries +go build ./cmd/orchestrator +go build ./cmd/portal -## Payment Flow +# Run tests (unit) +go test ./... -``` -Requester pays $1.00 - │ - ▼ Stripe processes - $0.029 + $0.30 processor fee → Stripe - │ - ▼ Net ≈ $0.671 - $0.00671 (1%) → SoHoLINK platform - │ - ▼ - $0.664 (99% of net) → Provider +# Run integration tests against an isolated test database +# (DB name MUST contain "test" — fixtures refuse to touch any other database) +TEST_DATABASE_URL="postgres://postgres:changeme@localhost:5432/soholink_test?sslmode=disable" \ + go test -tags integration ./... ``` -Lightning Network payments skip the Stripe fee entirely, making sub-cent micropayments economical for short tasks. +Database migrations are applied at service startup (golang-migrate, idempotent). The +full production stack — Postgres, SPIRE, orchestrator, portal, ingress — runs via Docker +Compose under `deploy/`. --- -## Security - -- **Ed25519 Federation Authentication** — every provider node signs its announce and heartbeat - messages with its Ed25519 private key; the coordinator verifies the signature against the - stored public key before accepting resource updates or heartbeats; forged registrations return - HTTP 401 -- **Rate Limiting on All Mutating Endpoints** — federation announce/deregister: 5 req/IP/min; - heartbeat: 10 req/IP/min; mobile WebSocket upgrades: 30 req/IP/min; mobile register: - 20 req/IP/min; implemented via a per-IP sliding-window `ipRateLimiter` -- **OPA-enforced resource limits** — providers cannot be exploited beyond their declared policy -- **TLS 1.2+ minimum** on all K8s edge connections and LND Lightning connections; x509 cert - pinning on LND via configurable `lnd_tls_cert_path` (PEM CA bundle) -- **HTLC payment gating** — Lightning hold invoices; payment only releases after result verification -- **Result replication** — mobile node results verified against a second node before settlement -- **Tamper-evident accounting** — SHA3-256 Merkle chain over all billing events -- **Startup config validation** — non-fatal warnings at startup for common misconfigurations: - default RADIUS secret, missing payment processor credentials, coordinator without HTTP API, - empty node DID, and LND without certificate pinning +## Status (honest) + +- **Built & running:** node recognition, matching/scheduling, the employment lifecycle, + fiat settlement (Stripe Connect), coordinator-signed fee declarations, the `/v0` + coordination wire, operator-or-SPIFFE authentication, and SPIFFE workload identity live + in production at **[soholink.org](https://soholink.org)** (trust domain + `spiffe://soholink.org`). +- **Single-coordinator deployment.** Cross-coordinator federation and witnessed + checkpoints are a **design target, not built** — the architecture's open problem 7 + (sovereign compute buys *mechanical*, not *economic*, exit) applies in full and is named, + not solved. +- **Operator enrollment** (front-end-as-operator) is verified in tests but has not + completed end-to-end in production, pending the two-factor mail transport. +- **No live pilot nodes yet.** The first pilot targets a dense residential community + adjacent to NTARI's headquarters. +- **The member economy is deliberately elsewhere** — credit, covenant, and record live in + the front end (Cloudy), one layer up. --- @@ -216,110 +176,19 @@ Lightning Network payments skip the Stripe fee entirely, making sub-cent micropa | Document | Description | |---|---| -| [BUILD.md](BUILD.md) | Build instructions, cross-compilation, CGO/MinGW setup | -| [docs/INSTALL.md](docs/INSTALL.md) | Installation and first-run guide | -| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | Full system design and component reference | -| [docs/TESTING.md](docs/TESTING.md) | Running tests and verifying deployments | -| [docs/OPERATIONS.md](docs/OPERATIONS.md) | Day-to-day node management | -| [docs/MOBILE_INTEGRATION.md](docs/MOBILE_INTEGRATION.md) | Mobile participation roadmap and implementation plan | -| [docs/research/ML_LOAD_BALANCING.md](docs/research/ML_LOAD_BALANCING.md) | ML scheduling research: RL, bandits, GNNs, LSTM, anomaly detection | -| [docs/research/SOHOLINK_CAPABILITIES.md](docs/research/SOHOLINK_CAPABILITIES.md) | Current capability assessment | -| [docs/research/MOBILE_PARTICIPATION.md](docs/research/MOBILE_PARTICIPATION.md) | Research: can mobile devices participate? | - ---- - -## Dependencies +| [`CONFORMANCE.md`](CONFORMANCE.md) | Role declaration in JFA terms; invariant-to-mechanism bindings; named stand-ins | +| [`CLAUDE.md`](CLAUDE.md) | Engineering context, conventions, and the working history | +| `docs/` | Architecture, operations runbooks, and per-session records | -**Core:** -- [`modernc.org/sqlite`](https://gitlab.com/cznic/sqlite) — Pure Go SQLite (no CGO required for CLI) -- [`fyne.io/fyne/v2`](https://fyne.io) — Cross-platform GUI toolkit (requires CGO for GUI build) -- [`github.com/open-policy-agent/opa`](https://github.com/open-policy-agent/opa) — Policy engine (Rego) -- [`github.com/shirou/gopsutil`](https://github.com/shirou/gopsutil) — Cross-platform hardware metrics -- [`github.com/stripe/stripe-go`](https://github.com/stripe/stripe-go) — Stripe payment processing -- [`github.com/gorilla/websocket`](https://github.com/gorilla/websocket) — WebSocket hub for mobile node connections - -**Observability:** -- `go.opentelemetry.io/otel` — Distributed tracing -- `github.com/prometheus/client_golang` — Metrics - -**Crypto:** -- `golang.org/x/crypto` — Ed25519, SHA3-256 -- `github.com/decred/dcrd/dcrec/secp256k1` — Secp256k1 for Lightning - -All dependencies are vendored (`vendor/`) for reproducible, offline builds. +The shared coordination protocol is specified in the +[`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol) repository +(`SPEC.md`). --- ## License -AGPL-3.0 — See [LICENSE.txt](LICENSE.txt) for details. - -This project is licensed under the GNU Affero General Public License v3.0, ensuring that all modifications remain open source and accessible to the community, supporting the federation sovereignty principles of SoHoLINK. - ---- - -## Mobile App - -The Flutter mobile app (`mobile/flutter-app/`) lets you **monitor your node** and **buy compute** from any phone or browser on your network. It includes a full buyer-side marketplace: browse provider nodes, configure workloads, estimate costs, top up your wallet, and launch jobs — all without leaving the app. - -### Changing the Node Address - -The app ships with the node address hardcoded for zero-setup access. To point it at a different machine, edit **one line**: - -```dart -// mobile/flutter-app/lib/api/soholink_client.dart (line ~17) -const kNodeUrl = 'http://192.168.1.220:4000'; -// ^^^^^^^^^^^^ change to your node's LAN IP -// ^^^^ change port if needed (fedaaa default: 8080) -``` - -After editing, rebuild the web bundle: - -```bash -cd mobile/flutter-app -flutter build web -# then restart the mock/preview server, or point to your live fedaaa instance -``` - -### Running the Preview Server (mock data) - -```bash -# From the repo root — serves Flutter web + mock API on port 4000 -python mobile/flutter-app/mock_server.py -``` - -Open `http://:4000` on any device on the same Wi-Fi. - -### Connecting to a Live Node - -Point `kNodeUrl` at your running `fedaaa` instance (default port 8080). -The node must expose these REST endpoints: - -| Endpoint | Description | -|---|---| -| `GET /api/health` | Returns `{"status":"ok"}` — used to verify connectivity | -| `GET /api/status` | Node metrics including `btc_usd_rate` for USD conversion | -| `GET /api/peers` | Federation peer list | -| `GET /api/revenue` | Earnings history and totals | -| `GET /api/workloads` | Active rental workloads | -| `GET /api/marketplace/nodes` | Browse available provider nodes (buyer flow) | -| `POST /api/marketplace/estimate` | Estimate workload cost in sats + USD | -| `POST /api/marketplace/purchase` | Buy and launch a workload | -| `GET /api/wallet/balance` | Prepaid wallet balance | -| `POST /api/wallet/topup` | Create Lightning invoice or Stripe intent to top up | -| `GET /api/orders` | Order history | -| `POST /api/orders/{id}/cancel` | Cancel order and receive proportional refund | - -### Currency Display - -All earnings are shown in **USD**, converted from satoshis using the live BTC/USD rate the node returns in `btc_usd_rate`. To change currency symbol or locale, update the `NumberFormat.currency(symbol: '\$', ...)` calls in: -- `lib/pages/dashboard_page.dart` -- `lib/pages/revenue_page.dart` -- `lib/pages/workloads_page.dart` -- `lib/pages/order_page.dart` (cost estimate and wallet balance cards) - ---- - -## Contributing +AGPL-3.0-or-later — see [`LICENSE.txt`](LICENSE.txt). The AGPL keeps the whole substrate a +permanent commons: read it, reimplement it, fork it, leave. -This project is part of the **Network Theory Applied Research Institute's** work on community computing infrastructure. Contributions welcome — open an issue or pull request. +*Network Theory Applied Research Institute, Inc. — 501(c)(3) — EIN 92-3047136 — info@ntari.org* diff --git a/README.pt.md b/README.pt.md new file mode 100644 index 0000000..10d2505 --- /dev/null +++ b/README.pt.md @@ -0,0 +1,204 @@ +> **Tradução comunitária (rascunho)** — política P2-002 da NTARI, Transmissão Multilíngue Global. Fonte: README.md (original em inglês, snapshot de 2026-07-29). Rascunho comunitário assistido por máquina, pendente de revisão pelo mantenedor regional conforme a P2-002 §3.1. As especificações técnicas centrais permanecem em inglês conforme a §2.2. +> +> Notou algum erro nesta tradução? Correções de tradução são contribuições +> valiosas e muito bem-vindas: faça um fork do repositório e abra um pull +> request em https://github.com/NTARI-RAND/SoHoLINK. + +# SoHoLINK + +[![Versão do Go](https://img.shields.io/badge/Go-1.24%2B-blue.svg)](https://golang.org) +[![Licença](https://img.shields.io/badge/License-AGPL%203.0-blue.svg)](LICENSE.txt) +[![CI](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml/badge.svg)](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml) + +**O coordenador de referência do substrato de computação SoHoLINK / Cloudy.** O SoHoLINK +transforma a capacidade ociosa de computação, armazenamento e impressão de máquinas +pertencentes aos participantes em um mercado coordenado: os membros contribuem com +hardware por meio de um front end e recebem pagamentos reais (em moeda fiduciária); +outros membros compram capacidade de computação, armazenamento, impressão e CDN sob demanda. + +> **Papel, em uma linha:** o SoHoLINK é o **coordenador** — ele orquestra o trabalho +> entre os nós e o liquida. Ele **não** é a economia de membros, e é uma parte +> **substituível**. Consulte [`CONFORMANCE.md`](CONFORMANCE.md) para a declaração +> completa de papel nos termos da própria arquitetura. + +--- + +## O que o SoHoLINK é + +O SoHoLINK realiza a **orquestração do lado do nó** para um substrato Janus-Facing +Architecture (JFA): + +- **Reconhecimento de nós** — os nós anunciam que trabalho farão por meio de listagens de capacidade assinadas. +- **Pareamento e agendamento** — alocação de cargas de trabalho nos nós (ciente de localidade, ciente de ociosidade e respeitando o opt-out). +- **Ciclo de vida do emprego** — oferta → aceitar/recusar → executar → reportar → liquidar, com uma janela de contestação. +- **Declarações de tarifas** — as tarifas existem apenas como mensagens assinadas pelo coordenador, legíveis e contestáveis. +- **Liquidação em moeda fiduciária** — repasses aos contribuidores via Stripe Connect. +- **Federação de front ends** — um objetivo de projeto (veja *Status* abaixo), ainda não construído. + +O coordenador é um papel **plugável e substituível.** Qualquer implementação conforme +pode substituí-lo, e um front end pode executar seu próprio coordenador ou fazer o +pareamento diretamente com os nós. Nada na rede é obrigado a passar por este +coordenador em particular — é essa ausência de privilégio que impede um coordenador +de se tornar um hub inamovível. + +## O que o SoHoLINK *não* é + +- **Não é a economia de membros do JFA.** Não há crédito emitido por membros, nem pacto de + reputação, nem registro selado por diálogo, nem julgamento de disputas voltado ao membro. + Isso vive no **front end** (Cloudy), por regra arquitetural. +- **Sem tokens, sem carteiras.** A liquidação é puramente em moeda fiduciária via Stripe + Connect, mantida estritamente separada do crédito de membro de qualquer front end. +- **Nenhuma pessoa na via de comunicação.** As contrapartes do SoHoLINK são front ends e + nós; a única identidade que ele manipula é a identidade da carga de trabalho (um `NodeID` + com vínculo SPIFFE). Identidade de membro, crédito, reputação e PII (dados pessoais) são + assuntos do front end. + +> **Superfícies transitórias.** O agente de nó (`internal/agent`, `cmd/agent`), o portal do +> membro (`internal/portal`, `cmd/portal`, `web/`) e a tabela `participants` são +> capacidades pertencentes ao front end que atualmente estão hospedadas neste repositório, +> herdadas da antiga era de papel duplo do SoHoLINK. Elas são mantidas em funcionamento e +> rotuladas como transitórias, aguardando migração para o front end. Não as trate como o +> papel de longo prazo do coordenador. + +--- + +## Onde ele se encaixa na pilha + +``` +Front end (Cloudy) ──┐ + ├──► sohocloud-protocol (the dependency leaf: coordination only) +Coordinator (this) ──┘ +``` + +- O SoHoLINK **consome o [`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol)** + em uma tag de versão publicada — o módulo de coordenação de cintura estreita (*thin waist*) que ele compartilha com o front end. +- Ele **serve a via `/v0` do protocolo** ao lado de suas próprias rotas HTTP existentes, de + modo que um front end conforme fala com ele pelo protocolo padrão enquanto as rotas + transitórias continuam funcionando. +- Ele **não** depende de nenhum front end nem de nenhum código da economia de membros. A + economia de membros vive acima desta camada e nunca deve migrar para baixo, para dentro dela. + +--- + +## Invariantes do JFA que este repositório sustenta + +| Invariante | Como é atendido aqui | +|---|---| +| Pessoas nunca aparecem na via de comunicação | As contrapartes são front ends e nós; a identidade na via é um `NodeID` SPIFFE | +| Identidade única de participante | Uma única tabela `participants` — sem separação provedor/consumidor no esquema ou no código | +| Legibilidade das tarifas | As tarifas existem apenas como mensagens `FeeDeclaration` assinadas pelo coordenador | +| A moeda fiduciária continua fiduciária; o crédito fica em casa | A liquidação é puramente Stripe Connect; estritamente separada do crédito de membro | +| Sem assimetria de informação | Preços, medição e ganhos são visíveis para os participantes | +| Superfície de governança separada | A administração/governança roda em uma interface separada, apenas local — nunca no site público, nunca atrás de flags de papel | +| Procedência de entrada = de saída | AGPL-3.0; assinatura DCO (*sign-off*); sem CLA | + +--- + +## Pilha tecnológica + +| Camada | Tecnologia | +|---|---| +| Linguagem | Go 1.24+ | +| Web | HTML renderizado no servidor via `html/template` do Go — sem framework JS, sem etapa de build (precisa funcionar em um celular Android de 2019 em 3G e em navegadores de Smart TV) | +| Banco de dados | PostgreSQL 16 + TimescaleDB, `pgx/v5` (sem ORM) | +| Armazenamento de objetos | MinIO (compatível com S3) | +| Identidade | SPIFFE/SPIRE — mTLS, SVIDs X.509 de curta duração | +| Pagamentos | Stripe Connect (apenas moeda fiduciária) | +| Implantação | Docker Compose atrás de um túnel Cloudflare | +| CI | GitHub Actions | + +--- + +## Estrutura do repositório + +``` +cmd/ + orchestrator/ Coordinator service: matching, employment lifecycle, /v0 wire, settlement hooks + portal/ Member portal (transitional, front-end-owned) + agent/ Node agent (transitional, front-end-owned) + seed/ Dev/load-test seeder — never point at production +internal/ + api/ Control-plane HTTP API (+ protocol /v0 handlers via protocoladapter) + orchestrator/ Node registry, matching, placement scoring, job token issuance + scheduler/ Scoring-based placement (class, freshness, capacity, locality, idle) + protocoladapter/ Implements coordinator.Coordinator; mounts the /v0 wire + payment/ Stripe Connect: onboarding, charge, payout, webhook + identity/ SPIFFE integration, mTLS config, SPIFFE-binding middleware + store/ PostgreSQL pool + migrations + agent/ portal/ Transitional front-end-owned capabilities (see note above) +web/ Server-rendered templates + CSS +deploy/ Compose stack, SPIRE config, backup + deploy scripts +docs/ Architecture, operations, and session records +``` + +--- + +## Build + +Pré-requisitos: Go 1.24+, uma instância de PostgreSQL 16 + TimescaleDB e Docker (para a +pilha completa). + +```bash +git clone https://github.com/NTARI-RAND/SoHoLINK +cd SoHoLINK + +# Build the coordinator and portal binaries +go build ./cmd/orchestrator +go build ./cmd/portal + +# Run tests (unit) +go test ./... + +# Run integration tests against an isolated test database +# (DB name MUST contain "test" — fixtures refuse to touch any other database) +TEST_DATABASE_URL="postgres://postgres:changeme@localhost:5432/soholink_test?sslmode=disable" \ + go test -tags integration ./... +``` + +As migrações do banco de dados são aplicadas na inicialização do serviço (golang-migrate, +idempotente). A pilha de produção completa — Postgres, SPIRE, orchestrator, portal, ingress +— roda via Docker Compose em `deploy/`. + +--- + +## Status (honesto) + +- **Construído e em funcionamento:** reconhecimento de nós, pareamento/agendamento, o ciclo + de vida do emprego, liquidação em moeda fiduciária (Stripe Connect), declarações de tarifas + assinadas pelo coordenador, a via de coordenação `/v0`, autenticação por operador ou SPIFFE + e a identidade de carga de trabalho SPIFFE estão em produção em + **[soholink.org](https://soholink.org)** (domínio de confiança `spiffe://soholink.org`). +- **Implantação com um único coordenador.** A federação entre coordenadores e os checkpoints + testemunhados são um **objetivo de projeto, não construídos** — o problema aberto 7 da + arquitetura (computação soberana compra saída *mecânica*, não *econômica*) se aplica + integralmente e está nomeado, não resolvido. +- **O cadastro de operador** (front end como operador) está verificado em testes, mas ainda + não foi concluído de ponta a ponta em produção, aguardando o transporte de e-mail de dois + fatores. +- **Ainda não há nós piloto ativos.** O primeiro piloto tem como alvo uma comunidade + residencial densa adjacente à sede da NTARI. +- **A economia de membros está deliberadamente em outro lugar** — crédito, pacto e registro + vivem no front end (Cloudy), uma camada acima. + +--- + +## Documentação + +| Documento | Descrição | +|---|---| +| [`CONFORMANCE.md`](CONFORMANCE.md) | Declaração de papel em termos do JFA; vínculos entre invariantes e mecanismos; substitutos nomeados | +| [`CLAUDE.md`](CLAUDE.md) | Contexto de engenharia, convenções e o histórico de trabalho | +| `docs/` | Arquitetura, runbooks de operação e registros por sessão | + +O protocolo de coordenação compartilhado é especificado no repositório +[`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol) +(`SPEC.md`). + +--- + +## Licença + +AGPL-3.0-or-later — veja [`LICENSE.txt`](LICENSE.txt). A AGPL mantém todo o substrato como +um bem comum permanente: leia-o, reimplemente-o, faça um fork dele, vá embora. + +*Network Theory Applied Research Institute, Inc. — 501(c)(3) — EIN 92-3047136 — info@ntari.org* diff --git a/README.tok.md b/README.tok.md new file mode 100644 index 0000000..c854984 --- /dev/null +++ b/README.tok.md @@ -0,0 +1,79 @@ +*toki pona:* lipu ni li lipu lili pi kulupu jan. ona li tan lawa NTARI "P2-002". lipu suli ale li lipu "README.md" pi toki Inli (tenpo suno 2026-07-29). ilo sona li pali e lipu ni; kulupu o lukin o pona e ona kepeken "P2-002" § 3.1. + +*English:* This is a condensed community rendering under NTARI policy P2-002. The complete document is the English original README.md (snapshot 2026-07-29). Machine-assisted draft pending community review per P2-002 section 3.1. + +sina lukin e pakala lon toki ni la o pona e ona: o pali e "fork" lon +https://github.com/NTARI-RAND/SoHoLINK, o pana e "pull request". pana sina +li pona tawa mi mute. + +# SoHoLINK + +## ni li seme + +SoHoLINK li **ilo lawa** ("coordinator") pi kulupu ilo "SoHoLINK / Cloudy". jan +li jo e ilo sona ona; tenpo mute la ilo ni li pali ala. SoHoLINK li kama jo e +wawa pali ni, e poki awen ni, e ken sitelen ni, li pana e ona tawa esun wan. jan +pana li kama jo e **mani lon** — ona li mani pi kulupu ala. jan ante li ken esun e +wawa pali, e poki awen, e sitelen, e pana sona ("CDN"). + +ona li pana e pali tawa ilo sona, li pini e pali, li pana e mani. taso ona li +**lawa ala** e nasin mani pi jan kulupu. ona li ijo pi ken ante: jan li ken pali e ilo +lawa ante, anu ilo sinpin li ken toki tawa ilo sona kepeken ala ona. tan ni la +ilo lawa wan li ken ala kama nena wan pi kulupu ale. (o lukin e `CONFORMANCE.md`.) + +## ona li pali e seme + +- **sona e ilo sona** — ilo sona li pana e lipu pi ken pali ona, kepeken sitelen + ken. +- **pana e pali** — ilo sona li poka anu seme? li pali ala anu seme? jan li wile + ala la, pali li tawa ala ona. +- **nasin pali** — pana e wile → kama ala kama → pali → toki e pini → pana e + mani. tenpo pi toki utala li lon kin. +- **lipu mani** — mani pi ilo lawa li lon lipu pi sitelen ken taso. jan ale li + ken lukin e ona, li ken toki utala e ona. +- **pana e mani** — kepeken ilo "Stripe Connect". mani lon taso; mani sitelen + ("token") ala; poki mani ala. + +## ona li seme ala + +jan li lon ala nasin toki ni. SoHoLINK li toki tawa ilo sinpin en ilo sona taso; +nimi pi ilo pali (`NodeID`, nasin "SPIFFE") li nimi wan taso pi ona. sona pi jan, +mani pi kulupu, sona pi pona jan, sitelen awen pi esun — ale ni li lon ilo sinpin +(Cloudy), lon sewi. + +ijo pi ilo sinpin li lon poki ni lon tenpo ni taso: `cmd/agent`, `cmd/portal`, en +poki `participants`. ona li kama tawa Cloudy lon tenpo kama. + +## ilo pi insa ona + +toki ilo "Go", poki sona "PostgreSQL", nasin nimi "SPIFFE/SPIRE". lipu sitelen li +tan ilo lawa taso — nasin "JS" ala, tan ni: ona o pali pona lon ilo lili pi tenpo +2019, lon nasin toki "3G", lon ilo lukin "Smart TV". + +## tenpo ni la + +- ni li pali, li lon [soholink.org](https://soholink.org): sona e ilo sona, pana + e pali, nasin pali, pana e mani, lipu mani, nasin toki `/v0`. +- ilo lawa **wan** taso li lon. kulupu pi ilo lawa mute li lon ala: jan li ken + weka e ilo ona, taso ona li ken ala weka tan esun ale ("open problem" #7). lipu + li toki e pakala ni, li pona ala e ona. +- ilo sona pi jan kulupu li lon ala. pali open nanpa wan li kama lon ma pi tomo + mute, lon poka pi tomo lawa NTARI. + +## sina ken kama pali + +```bash +git clone https://github.com/NTARI-RAND/SoHoLINK +cd SoHoLINK +go build ./cmd/orchestrator +go test ./... +``` + +nasin toki pi kulupu ale li lon poki +[`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol) (lipu +`SPEC.md`). sona pali li lon `CLAUDE.md` en `docs/`. + +lawa lipu: AGPL-3.0-or-later — o lukin, o pali sin, o kipisi, o weka. kulupu ilo +ni li ijo pi jan ale lon tenpo ale. + +*Network Theory Applied Research Institute, Inc. — 501(c)(3) — EIN 92-3047136 — info@ntari.org* diff --git a/README.zh.md b/README.zh.md new file mode 100644 index 0000000..82704ea --- /dev/null +++ b/README.zh.md @@ -0,0 +1,188 @@ +> 社区翻译(草稿)—— NTARI 政策 P2-002《全球多语言广播政策》。来源:README.md(英文原版,快照日期 2026-07-29)。本文为机器辅助的社区翻译草稿,尚待区域维护者依据 P2-002 §3.1 审校。根据 §2.2,核心技术规范仍以英文为准。 +> +> 如发现译文有误,欢迎 fork 仓库并提交 Pull Request +> 来改进翻译:https://github.com/NTARI-RAND/SoHoLINK。翻译修正与代码贡献同样宝贵,我们诚挚欢迎。 + +# SoHoLINK + +[![Go 版本](https://img.shields.io/badge/Go-1.24%2B-blue.svg)](https://golang.org) +[![许可证](https://img.shields.io/badge/License-AGPL%203.0-blue.svg)](LICENSE.txt) +[![CI](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml/badge.svg)](https://github.com/NTARI-RAND/SoHoLINK/actions/workflows/ci.yml) + +**SoHoLINK / Cloudy 计算基底(compute substrate)的参考协调器(reference coordinator)。** +SoHoLINK 将参与者自有设备上闲置的计算、存储和打印能力转化为一个有组织协调的市场: +成员通过前端贡献硬件并获得真实的(法币)报酬;其他成员则按需购买计算、存储、打印 +和 CDN 容量。 + +> **一句话概括其角色:** SoHoLINK 是**协调器**——它在各节点之间编排工作并完成结算。 +> 它**不是**成员经济,并且是一个**可替换**的组成部分。完整的角色声明(以该架构自身 +> 的术语表述)见 [`CONFORMANCE.md`](CONFORMANCE.md)。 + +--- + +## SoHoLINK 是什么 + +SoHoLINK 为 Janus-Facing Architecture(JFA)基底执行**节点侧编排**: + +- **节点识别** —— 节点通过带签名的能力清单(capability listings)声明自己愿意承接的工作。 +- **匹配与调度** —— 将工作负载放置到节点上(感知本地性、感知空闲状态、尊重节点的退出选择)。 +- **雇佣生命周期** —— 报价 → 接受/拒绝 → 运行 → 报告 → 结算,并附带争议窗口期。 +- **费用声明** —— 费用只以协调器签名的、清晰可读且可提出异议的消息形式存在。 +- **法币结算** —— 通过 Stripe Connect 向贡献者支付报酬。 +- **前端联邦** —— 属于设计目标(见下文*现状*),尚未构建。 + +协调器是一个**可插拔、可替换的角色**。任何符合规范的实现都可以替换它,前端也可以 +运行自己的协调器,或直接与节点进行匹配。网络中没有任何环节被要求必须经由这个特定 +的协调器路由——正是这种非特权地位,防止了协调器演变为不可移除的中心枢纽。 + +## SoHoLINK *不是*什么 + +- **不是 JFA 的成员经济。** 没有成员发行的信用,没有声誉契约(reputation covenant), + 没有对话封存记录(dialog-sealed record),也没有面向成员的争议裁决。按照架构规则, + 这些都位于**前端**(Cloudy)中。 +- **没有代币,没有钱包。** 结算完全通过 Stripe Connect 以法币进行,并与任何前端的 + 成员信用严格分离。 +- **通信线路上不出现自然人。** SoHoLINK 的交互对手是前端和节点;它处理的唯一身份是 + 工作负载身份(带有 SPIFFE 绑定的 `NodeID`)。成员身份、信用、声誉和个人身份信息 + (PII)均由前端负责。 + +> **过渡性组件。** 节点代理(`internal/agent`、`cmd/agent`)、成员门户 +> (`internal/portal`、`cmd/portal`、`web/`)以及 `participants` 表属于前端所有的 +> 能力,因 SoHoLINK 早期身兼双重角色而暂时托管在本仓库中。它们会保持可用并被标记 +> 为过渡性组件,等待迁移到前端。请勿将其视为协调器的长期职责。 + +--- + +## 它在技术栈中的位置 + +``` +Front end (Cloudy) ──┐ + ├──► sohocloud-protocol (the dependency leaf: coordination only) +Coordinator (this) ──┘ +``` + +- SoHoLINK 以已发布的版本标签**消费 [`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol)** + ——这是它与前端共享的“细腰”(thin-waist)协调模块。 +- 它在自身既有 HTTP 路由之外**同时提供该协议的 `/v0` 通信线路(wire)**,因此符合 + 规范的前端可以通过标准协议与它通信,而过渡性路由仍可继续工作。 +- 它**不**依赖任何前端,也**不**依赖任何成员经济代码。成员经济位于此层之上, + 绝不能向下迁移到这一层中。 + +--- + +## 本仓库遵守的 JFA 不变量 + +| 不变量 | 在本仓库中的实现方式 | +|---|---| +| 通信线路上绝不出现自然人 | 交互对手是前端和节点;线路上的身份是 SPIFFE `NodeID` | +| 单一参与者身份 | 只有一张 `participants` 表——数据库模式和代码中均不区分提供方/消费方 | +| 费用透明可读 | 费用只以协调器签名的 `FeeDeclaration` 消息形式存在 | +| 法币归法币,信用留原处 | 结算完全通过 Stripe Connect 进行,与成员信用严格分离 | +| 无信息不对称 | 定价、计量和收益对参与者可见 | +| 治理界面分离 | 管理/治理运行在独立的、仅限本地访问的界面上——绝不放在公共站点上,也绝不藏在角色开关(role flags)之后 | +| 输入与输出的许可来源对等 | AGPL-3.0;DCO 签署(sign-off);无 CLA | + +--- + +## 技术栈 + +| 层 | 技术 | +|---|---| +| 语言 | Go 1.24+ | +| Web | 通过 Go `html/template` 服务端渲染 HTML——无 JS 框架、无构建步骤(必须能在使用 3G 网络的 2019 款 Android 手机及智能电视浏览器中正常工作) | +| 数据库 | PostgreSQL 16 + TimescaleDB,`pgx/v5`(不使用 ORM) | +| 对象存储 | MinIO(兼容 S3) | +| 身份 | SPIFFE/SPIRE——mTLS、短生命周期的 X.509 SVID | +| 支付 | Stripe Connect(仅法币) | +| 部署 | Docker Compose,置于 Cloudflare 隧道之后 | +| CI | GitHub Actions | + +--- + +## 仓库结构 + +``` +cmd/ + orchestrator/ Coordinator service: matching, employment lifecycle, /v0 wire, settlement hooks + portal/ Member portal (transitional, front-end-owned) + agent/ Node agent (transitional, front-end-owned) + seed/ Dev/load-test seeder — never point at production +internal/ + api/ Control-plane HTTP API (+ protocol /v0 handlers via protocoladapter) + orchestrator/ Node registry, matching, placement scoring, job token issuance + scheduler/ Scoring-based placement (class, freshness, capacity, locality, idle) + protocoladapter/ Implements coordinator.Coordinator; mounts the /v0 wire + payment/ Stripe Connect: onboarding, charge, payout, webhook + identity/ SPIFFE integration, mTLS config, SPIFFE-binding middleware + store/ PostgreSQL pool + migrations + agent/ portal/ Transitional front-end-owned capabilities (see note above) +web/ Server-rendered templates + CSS +deploy/ Compose stack, SPIRE config, backup + deploy scripts +docs/ Architecture, operations, and session records +``` + +--- + +## 构建 + +先决条件:Go 1.24+、一个 PostgreSQL 16 + TimescaleDB 实例,以及 Docker(用于运行 +完整技术栈)。 + +```bash +git clone https://github.com/NTARI-RAND/SoHoLINK +cd SoHoLINK + +# Build the coordinator and portal binaries +go build ./cmd/orchestrator +go build ./cmd/portal + +# Run tests (unit) +go test ./... + +# Run integration tests against an isolated test database +# (DB name MUST contain "test" — fixtures refuse to touch any other database) +TEST_DATABASE_URL="postgres://postgres:changeme@localhost:5432/soholink_test?sslmode=disable" \ + go test -tags integration ./... +``` + +数据库迁移在服务启动时自动应用(golang-migrate,幂等)。完整的生产技术栈—— +Postgres、SPIRE、orchestrator、portal、入口网关(ingress)——通过 `deploy/` 目录 +下的 Docker Compose 运行。 + +--- + +## 现状(如实说明) + +- **已构建并在运行:** 节点识别、匹配/调度、雇佣生命周期、法币结算(Stripe Connect)、 + 协调器签名的费用声明、`/v0` 协调通信线路、运营方或 SPIFFE 认证,以及 SPIFFE 工作 + 负载身份,均已在 **[soholink.org](https://soholink.org)** 的生产环境中运行(信任域 + `spiffe://soholink.org`)。 +- **单协调器部署。** 跨协调器联邦与见证检查点(witnessed checkpoints)属于**设计目标, + 尚未构建**——该架构的开放问题 7(自主计算换来的是*机械性*退出,而非*经济性*退出) + 在此完全适用;这一问题已被明确指出,但尚未解决。 +- **运营方注册**(前端作为运营方)已在测试中得到验证,但尚未在生产环境中完成端到端 + 流程,等待双因素邮件传输机制就绪。 +- **尚无正式运行的试点节点。** 首个试点面向紧邻 NTARI 总部的一个高密度住宅社区。 +- **成员经济被有意放在别处**——信用、契约和记录位于上一层的前端(Cloudy)中。 + +--- + +## 文档 + +| 文档 | 说明 | +|---|---| +| [`CONFORMANCE.md`](CONFORMANCE.md) | 以 JFA 术语表述的角色声明;不变量与机制的绑定关系;已明确命名的临时替代方案(stand-ins) | +| [`CLAUDE.md`](CLAUDE.md) | 工程背景、约定与工作历史 | +| `docs/` | 架构、运维手册及按会话记录的文档 | + +共享的协调协议在 [`sohocloud-protocol`](https://github.com/NTARI-RAND/sohocloud-protocol) +仓库中定义(`SPEC.md`)。 + +--- + +## 许可证 + +AGPL-3.0-or-later——见 [`LICENSE.txt`](LICENSE.txt)。AGPL 使整个基底始终保持为永久的 +公共资源(commons):你可以阅读它、重新实现它、分叉(fork)它,也可以随时离开。 + +*Network Theory Applied Research Institute, Inc. — 501(c)(3) — EIN 92-3047136 — info@ntari.org*