Eldermind Astro Engine API
Officialby 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).
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues