Skip to main content
Glama
ElderMindAI

Eldermind Astro Engine API

Official
by ElderMindAI
README.md
# Eldermind Astro Engine API

Osiem systemów ezoterycznych. Jedno API. Gotowe dla AI.

REST pod `/v1/*` i serwer **MCP** pod `/mcp` — dwa interfejsy nad tym samym
rdzeniem [`eldermind-core`](https://github.com/ElderMindAI/eldermind-core),
w jednym procesie. Zero duplikacji logiki: cache, limit współbieżności, kredyty
i obsługa błędów istnieją w jednym egzemplarzu.

## Co liczy

Astrologia zachodnia · astrologia wedyjska (Jyotish) · Human Design · Gene Keys ·
Matryca Losu · BaZi (Cztery Filary) · numerologia pitagorejska · karta drakoniczna.
Plus Animal Design dla psów, kotów i koni.

Wszystko lokalnie na Swiss Ephemeris. **Żadnego zewnętrznego API astrologicznego
w torze wykonania.**

## Trzy własności, na których stoi kontrakt

**Determinizm.** Każde obliczenie jest czystą funkcją swoich argumentów. Przypnij
`reference_date`, a te same dane wejściowe zwrócą te same bajty bezterminowo.
29 testów złotych wywala build, jeśli ruszy się choć jedna liczba.

**Poziomy szczegółowości.** Pełny profil to ~30 KB, czyli ~7 700 tokenów — jedno
wywołanie narzędzia zjadłoby kontekst modelu, zanim ten zdąży cokolwiek powiedzieć.
`detail: "summary"` daje ~2 KB samych wniosków.

| Poziom | Rozmiar | Zawartość |
|---|---|---|
| `summary` | ~2,2 KB | tylko wnioski — **domyślny dla MCP** |
| `standard` | ~18 KB | wszystkie pozycje, bez tablic historycznych — domyślny dla REST |
| `full` | ~30 KB | + oś Dasha (100 lat), pełne Da Yun, aktywacje HD |

**Częściowe powodzenie.** W bundlu jeden system, który zawiedzie, nie kosztuje Cię
pozostałych siedmiu — błąd ląduje w `meta.errors[]`, reszta wraca normalnie.
Urodzony w Tromsø dostaje 7 z 8 systemów zamiast błędu (Placidus jest za kołem
podbiegunowym matematycznie nieokreślony).

## Szybki start

Rdzeń jest osobnym repozytorium i **nie ma go na PyPI**, więc trzeba go
sklonować obok i zainstalować pierwszy — w odwrotnej kolejności `pip` próbuje
pobrać `eldermind-core` z sieci i przerywa instalację.

```bash
git clone https://github.com/ElderMindAI/eldermind-core.git
git clone https://github.com/ElderMindAI/eldermind-astro-api.git
cd eldermind-astro-api

python -m venv .venv && . .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -e ../eldermind-core
pip install -e ".[dev,mcp]"
cp .env.example .env.local
uvicorn app.main:app --port 8010 --reload
```

Wymagany Python 3.11+. Ekstras `[mcp]` nie jest opcjonalny w praktyce: bez niego
serwis wstaje, odpowiada 200 na `/health` i ma komplet tras REST — ale nie ma
`/mcp`, czyli tego, na czym stoi produkt.

Dokumentacja interaktywna: <http://127.0.0.1:8010/docs>

```bash
curl -X POST http://127.0.0.1:8010/v1/profile/complete \
  -H "Authorization: Bearer sk_test_development" \
  -H "Content-Type: application/json" \
  -d '{"subject":{"birth_date":"1993-09-01","birth_time":"14:30",
       "latitude":52.2297,"longitude":21.0122,"timezone":"Europe/Warsaw",
       "gender":"male"},"detail":"summary"}'
```

## Podłączenie do Claude / Cursor / VS Code

```jsonc
// .cursor/mcp.json  ·  Claude Desktop: analogicznie
{
  "mcpServers": {
    "eldermind-astro": {
      "url": "https://api.eldermind.io/mcp",
      "headers": { "Authorization": "Bearer sk_live_TWOJ_KLUCZ" }
    }
  }
}
```

Lokalnie, przez stdio: `python run_mcp_stdio.py`.

### Claude.ai / ChatGPT — bez kopiowania kluczy (OAuth 2.1)

Użytkownik podaje **wyłącznie URL** `https://api.eldermind.io/mcp` i przechodzi
logowanie. Reszta jest odkrywana automatycznie:

| Krok | Standard | Endpoint |
|---|---|---|
| 401 wskazuje metadane | RFC 9728 | `WWW-Authenticate: ... resource_metadata="..."` |
| Metadane zasobu | RFC 9728 | `/.well-known/oauth-protected-resource/mcp` |
| Metadane serwera autoryzacji | RFC 8414 | `/.well-known/oauth-authorization-server` |
| Rejestracja klienta | RFC 7591 | `POST /register` |
| Autoryzacja + PKCE | OAuth 2.1 | `GET /authorize` → ekran zgody → `POST /token` |
| Odwołanie | RFC 7009 | `POST /revoke` |

**Token OAuth to delegacja istniejącego konta, nie nowe konto.** Ekran zgody
prosi raz o klucz API; wydany token nosi jego identyfikator. Dzięki temu
uprawnienia, kredyty i limity działają identycznie niezależnie od tego, czy
żądanie przyszło z `Bearer sk_live_...`, czy z tokenu OAuth — reguły żyją
w jednym miejscu.

**Zakresy zawężają, nigdy nie poszerzają.** Efektywny dostęp to część wspólna
uprawnień planu i zakresów tokenu. Zgoda na `system:bazi` nie da dostępu do
wedyjskiej, a plan obejmujący wszystko i tak nie przekroczy tego, na co
użytkownik się zgodził. Katalog zakresów: `GET /oauth/scopes`.

Access token żyje godzinę, refresh 30 dni i **rotuje przy każdym użyciu** — skradziony
działa tylko do najbliższego odświeżenia przez prawdziwego klienta. Kod
autoryzacyjny jest jednorazowy. Odwołanie klucza natychmiast unieważnia wszystkie
wydane na niego tokeny.

### 14 narzędzi

| Narzędzie | Kredyty |
|---|---|
| `resolve_birth_data` — nazwa miejsca → współrzędne i strefa | 0 |
| `get_planetary_positions` — niebo o dowolnej porze, bez danych urodzeniowych | 1 |
| `get_western_chart` · `get_human_design` · `get_gene_keys` · `get_matrix_of_destiny` · `get_bazi` · `get_numerology` · `get_draconic_chart` | 1 |
| `get_vedic_chart` · `get_animal_design` | 2 |
| **`get_complete_profile`** — wszystkie 8 systemów naraz | **6** |
| `lookup_knowledge` — opis bramy, kanału, linii, Gene Key | 1 |
| `get_usage` — stan kredytów | 0 |

Bundle kosztuje 6 zamiast 9 — rabat jest narzędziem projektowym, nie promocją:
**steruje zachowaniem modelu ceną**, żeby wybierał jedno wywołanie zamiast ośmiu.

**Zasoby:** `eldermind://systems`, `eldermind://methodology`
**Prompty:** `natal_reading`, `timing_advice`, `compatibility_brief`

### Dlaczego akurat tak

- **`resolve_birth_data` jest osobnym narzędziem**, bo model ma „Kraków", nigdy
  52.23/21.01. Bez tego kroku każdy przepływ wykłada się na pierwszym pytaniu.
- **Nazwy, nie kody.** `"Manifesting Generator"`, nie `"type_2"`. Model ma to
  rozumieć bez tablicy odwzorowań.
- **Błędy niosą instrukcję.** Komunikat przy wyczerpanych kredytach mówi wprost:
  *„poinformuj użytkownika i wskaż stronę cennika — nie wymyślaj wyniku"*. Model,
  który dostanie sam kod błędu, dopowie sobie kartę.
- **Ostrzeżenia zamiast fałszywej precyzji.** Brak godziny urodzenia naprawdę
  psuje Ascendent, domy i Księżyc — `warnings` mówi to modelowi wprost.

## Kontrakt błędów

Każda awaria wygląda tak samo:

```json
{"error": {
  "code": "AMBIGUOUS_LOCAL_TIME",
  "message": "Local time 02:30:00 on 1993-03-28 does not exist in Europe/Warsaw (daylight-saving gap).",
  "field": "birth_time",
  "request_id": "req_01JD8X...",
  "docs_url": "https://eldermind.io/api/docs/errors#ambiguous-local-time"
}}
```

`INVALID_API_KEY` · `INSUFFICIENT_CREDITS` · `SYSTEM_NOT_ENTITLED` ·
`INVALID_TIMEZONE` · `AMBIGUOUS_LOCAL_TIME` · `DATE_OUT_OF_RANGE` ·
`HOUSE_SYSTEM_UNAVAILABLE` · `GEOCODING_FAILED` · `RATE_LIMITED` ·
`SERVICE_BUSY` · `CALCULATION_ERROR`

## Ograniczenia — świadome i udokumentowane

- **Bez godziny urodzenia** przyjmujemy 12:00; Ascendent, domy, filar godziny
  i Księżyc są niewiarygodne. Zawsze oflagowane w `warnings`.
- **Za kołem podbiegunowym** Placidus jest nieokreślony. Karta zachodnia zwraca
  typowany błąd z podpowiedzią; wedyjska liczy się dalej (Whole Sign działa
  wszędzie).
- **Przejścia czasu letniego** — godzina z luki wiosennej nigdy nie istniała,
  z nakładki jesiennej wystąpiła dwa razy. Odrzucamy obie zamiast zgadywać.
- **Zakres dat** 1800–2200.

## Bezpieczeństwo i RODO

Klucze: **HMAC-SHA256 z pepperem**, plaintext nigdy nie trafia do bazy —
przechowujemy hash i krótki prefiks (`sk_live_a1b2…`), po którym użytkownik
rozpoznaje własne klucze w panelu. Pepper żyje w środowisku, nie w bazie, więc
sam wyciek bazy nie wystarczy do podrobienia klucza — i, co ciekawsze, nie
wystarczy też **zapis** do bazy. Hashe sprzed tej zmiany zaczynają się od
`$argon2id$` i są nadal akceptowane przy weryfikacji.

Klucz cache'u to SHA-256 wejść — nie da się z niego odtworzyć daty urodzenia.
`usage_events` zawiera wyłącznie metryki; data urodzenia i imię **nigdy** nie
trafiają do zapisu ani do logów. Test tego pilnuje.

## Testy

```bash
pytest                        # 281 testów
pytest ../eldermind-core      # 122 testy, w tym 29 złotych
```

## Licencja

Kod jest **udostępniony do wglądu, nie open source**. Wolno go czytać, studiować
i oceniać; użycie w produkcie lub usłudze wymaga pisemnej zgody. Pełne warunki:
[`LICENSE`](LICENSE).